Day 17: Trait Objects
Harddyn TraitDynamic DispatchBox

Day 17: Trait Objects

Trait objects enable dynamic dispatch - deciding which method to call at runtime.

Static vs Dynamic Dispatch

// Static dispatch (monomorphization)
fn notify(item: &impl Summary) { ... }

// Dynamic dispatch (trait object)
fn notify(item: &dyn Summary) { ... }

Creating Trait Objects

trait Draw {
    fn draw(&self);
}

let shapes: Vec<Box<dyn Draw>> = vec![
    Box::new(Circle { radius: 5.0 }),
    Box::new(Rectangle { width: 10.0, height: 5.0 }),
];

Trait objects use Box<dyn Trait> because the size is unknown at compile time. The Box provides heap allocation with a known pointer size.

When to Use Trait Objects

Use CaseApproach
Homogeneous collectionVec<T> with generics
Heterogeneous collectionVec<Box<dyn Trait>>
Plugin systemsTrait objects
Maximum performanceGenerics (static dispatch)

Object Safety

Not all traits can be made into trait objects. A trait is object-safe if:

  • No Self in method return types
  • No generic type parameters in methods

The Task

  1. Implement the Speak trait for Cat (return "Meow!")
  2. Create a Vec<Box<dyn Speak>> with a Dog and Cat
  3. Iterate and print each animal's speech

Requirements

  • Dog.speak()"Woof!"
  • Cat.speak()"Meow!"
  • Output two lines: Woof! then Meow!

Hints

impl Speak for Cat {
    fn speak(&self) -> String {
        String::from("Meow!")
    }
}

fn main() {
    let animals: Vec<Box<dyn Speak>> = vec![
        Box::new(Dog),
        Box::new(Cat),
    ];
    
    for animal in &animals {
        println!("{}", animal.speak());
    }
}
Language: Rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Output
Run to see the result here.
    Day 17: Trait Objects · RUST Challenge | learn.sol