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 types 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<_>>());
}