Rust Trait Objects
Choose dynamic dispatch when one collection needs different concrete types.
How it works
A trait object uses a trait interface behind a pointer and selects the concrete implementation at runtime. It can represent different types in one collection when the trait supports dynamic dispatch. This differs from a generic function specialised for concrete types. Consider allocation, ownership and the trait’s allowed methods when choosing a design rather than treating dynamic dispatch as a universal abstraction.
Run the code
Reviewed with Rust 1.97.0, edition 2024, using the standard library only. Save the complete download as lesson-name.rs in a separate learning folder, compile with rustc --edition=2024 lesson-name.rs and run the resulting program (lesson-name.exe on Windows). Use the actual lesson filename. The final project includes complete Cargo package files; run cargo test --offline and cargo run --offline from that separate package folder. There is no Rust browser runner; PHP, Apache and MySQL are not needed.
This complete example was executed in the stated local review environment.
Example
fn main() {
trait Label { fn label(&self) -> &str; }
struct Tray;
struct Basket;
impl Label for Tray { fn label(&self) -> &str { "tray" } }
impl Label for Basket { fn label(&self) -> &str { "basket" } }
let items: Vec<Box<dyn Label>> = vec![Box::new(Tray), Box::new(Basket)];
assert_eq!(items.iter().map(|x| x.label()).collect::<Vec<_>>(), vec!["tray","basket"]);
println!("Dynamic labels: tray, basket");
}
Expected result
Dynamic labels: tray, basket
Each Box owns a different concrete value while exposing the same Label interface. The returned text is borrowed for the call and is not an independently owned String. A simple enum might be preferable if the set of variants is closed and exhaustive matching is valuable.
Primary technical reference: Rust documentation.