Owned Trait Objects
We previously saw how trait objects can be used with references, e.g &dyn Pet. However, we can also use trait objects with smart pointers like Box to create an owned trait object: Box<dyn Pet>.
1. ```
struct Dog {
```
2. ```
name: String,
```
3. ```
age: i8,
```
4. ```
}
```
5. ```
struct Cat {
```
6. ```
lives: i8,
```
7. ```
}
```
9. ```
trait Pet {
```
10. ```
fn talk(&self) -> String;
```
11. ```
}
```
13. ```
impl Pet for Dog {
```
14. ```
fn talk(&self) -> String {
```
15. ```
format!("Woof, my name is {}!", self.name)
```
16. ```
}
```
17. ```
}
```
19. ```
impl Pet for Cat {
```
20. ```
fn talk(&self) -> String {
```
21. ```
String::from("Miau!")
```
22. ```
}
```
23. ```
}
```
25. ```
fn main() {
```
26. ```
let pets: Vec<Box<dyn Pet>> = vec![
```
27. ```
Box::new(Cat { lives: 9 }),
```
28. ```
Box::new(Dog { name: String::from("Fido"), age: 5 }),
```
29. ```
];
```
30. ```
for pet in pets {
```
31. ```
println!("Hello, who are you? {}", pet.talk());
```
32. ```
}
```
33. ```
}
```
Memory layout after allocating pets:

This slide should take about 10 minutes.
- Types that implement a given trait may be of different sizes. This makes it impossible to have things like
Vec<dyn Pet>in the example above. dyn Petis a way to tell the compiler about a dynamically sized type that implementsPet.- In the example,
petsis allocated on the stack and the vector data is on the heap. The two vector elements are fat pointers: - A fat pointer is a double-width pointer. It has two components: a pointer to the actual object and a pointer to the virtual method table (vtable) for the
Petimplementation of that particular object. - The data for the
Dognamed Fido is thenameandagefields. TheCathas alivesfield. - Compare these outputs in the above example:
1. println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>());
2. println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>());
3. println!("{}", std::mem::size_of::<&dyn Pet>());
4. println!("{}", std::mem::size_of::<Box<dyn Pet>>());
