Trait Objects
We’ve seen how a function can take arguments which implement a trait:
use std::fmt::Display; fn print<T: Display>(x: T) { println!("Your value: {}", x); } fn main() { print(123); print("Hello"); }
However, how can we store a collection of mixed types which implement Display
?
fn main() { let xs = vec![123, "Hello"]; }
For this, we need trait objects:
use std::fmt::Display; fn main() { let xs: Vec<Box<dyn Display>> = vec![Box::new(123), Box::new("Hello")]; for x in xs { println!("x: {x}"); } }
Memory layout after allocating xs
:
Similarly, you need a trait object if you want to return different values implementing a trait:
fn numbers(n: i32) -> Box<dyn Iterator<Item=i32>> { if n > 0 { Box::new(0..n) } else { Box::new((n..0).rev()) } } fn main() { println!("{:?}", numbers(-5).collect::<Vec<_>>()); println!("{:?}", numbers(5).collect::<Vec<_>>()); }