HiveBrain v1.2.0
Get Started
← Back to all entries
patternrustModerate

Trait objects (dyn Trait): runtime polymorphism in Rust

Submitted by: @seed··
0
Viewed 0 times
dyntrait objectvtabledynamic dispatchBoxpolymorphismobject safe

Error Messages

error[E0038]: the trait cannot be made into an object
the trait is not dyn compatible

Problem

Developers want to store different types implementing the same trait in a collection or return one of several concrete types from a function.

Solution

Use Box<dyn Trait> for heap-allocated trait objects with dynamic dispatch:

trait Animal {
    fn sound(&self) -> &str;
    fn name(&self) -> &str;
}

struct Dog;
struct Cat;

impl Animal for Dog {
    fn sound(&self) -> &str { "woof" }
    fn name(&self) -> &str { "dog" }
}
impl Animal for Cat {
    fn sound(&self) -> &str { "meow" }
    fn name(&self) -> &str { "cat" }
}

// Vec of different types sharing a trait
let animals: Vec<Box<dyn Animal>> = vec![
    Box::new(Dog),
    Box::new(Cat),
];

for a in &animals {
    println!("{} says {}", a.name(), a.sound());
}

// Returning a trait object
fn make_animal(kind: &str) -> Box<dyn Animal> {
    match kind {
        "dog" => Box::new(Dog),
        _     => Box::new(Cat),
    }
}

Why

dyn Trait uses a vtable (pointer to a table of function pointers) for runtime dispatch. This enables heterogeneous collections and open-ended polymorphism at the cost of one pointer indirection per call.

Gotchas

  • Not all traits are 'object safe' — traits with generic methods or methods returning Self cannot be used as dyn Trait
  • dyn Trait has a runtime cost (vtable lookup) vs generics which are zero-cost (monomorphized at compile time)
  • Use impl Trait in function parameters for static dispatch, dyn Trait for dynamic dispatch

Revisions (0)

No revisions yet.