use std::fmt;
// A custom type for which we will implement the `fmt::Display` trait.
struct CanDisplay;
impl fmt::Display for CanDisplay {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CanDisplay")
}
}
// A different custom type that also implements the `fmt::Display` trait.
struct AnotherCanDisplay;
impl fmt::Display for AnotherCanDisplay {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "AnotherCanDisplay")
}
}
// A function that takes a trait object.
// The `dyn` keyword is used to indicate dynamic dispatch.
// This function can accept any type that implements `fmt::Display`.
fn show_item_dynamic(item: &dyn fmt::Display) {
println!("{}", item);
}
fn main() {
let my_struct = CanDisplay;
let my_other_struct = AnotherCanDisplay;
let my_string = String::from("Hello from a String");
// All these types can be passed to the same function because they
// all satisfy the `&dyn fmt::Display` trait object.
show_item_dynamic(&my_struct);
show_item_dynamic(&my_other_struct);
show_item_dynamic(&my_string);
// Dynamic dispatch is particularly useful for heterogeneous collections.
// This isn't possible with static dispatch.
let items: Vec<&dyn fmt::Display> = vec![
&my_struct,
&my_other_struct,
&my_string,
&42, // An `i32` also implements `fmt::Display`
];
for item in items {
show_item_dynamic(item);
}
}