Trait Objects

We’ve seen how a function can take arguments which implement a trait:

1. use std::fmt::Display;

3. fn print<T: Display>(x: T) {
4. println!("Your value: {x}");
5. }

7. fn main() {
8. print(123);
9. print("Hello");
10. }

However, how can we store a collection of mixed types which implement Display?

1. fn main() {
2. let xs = vec![123, "Hello"];
3. }

For this, we need trait objects:

1. use std::fmt::Display;

3. fn main() {
4. let xs: Vec<Box<dyn Display>> = vec![Box::new(123), Box::new("Hello")];
5. for x in xs {
6. println!("x: {x}");
7. }
8. }

Memory layout after allocating xs:

24.7. Trait Objects - 图1

Similarly, you need a trait object if you want to return different types implementing a trait:

1. fn numbers(n: i32) -> Box<dyn Iterator<Item=i32>> {
2. if n > 0 {
3. Box::new(0..n)
4. } else {
5. Box::new((n..0).rev())
6. }
7. }

9. fn main() {
10. println!("{:?}", numbers(-5).collect::<Vec<_>>());
11. println!("{:?}", numbers(5).collect::<Vec<_>>());
12. }