It is possible to create a function that accepts objects that implement a specific trait.
fn generic_speak<T: Speak>(speaker: &T) {
println!("{0}", speaker.speak());
}
fn main() {
let person = Person {};
let dog = Dog {};
generic_speak(&person);
generic_speak(&dog);
}
Static dispatch is used here, which means that Rust compiler will generate specialized versions of generic_speak
function for both Dog
and Person
types. This generation of specialized versions of a polymorphic function (or any polymorphic entity) during compilation is called Monomorphization.
fn generic_speak(speaker: &Speak) {
println!("{0}", speaker.speak());
}
fn main() {
let person = Person {};
let dog = Dog {};
generic_speak(&person as &Speak);
generic_speak(&dog); // gets automatically coerced to &Speak
}
Here, only a single version of generic_speak
exists in the compiled binary, and the speak()
call is made using a vtable lookup at runtime. Thus, using dynamic dispatch results in faster compilation and smaller size of compiled binary, while being slightly slower at runtime.
Objects of type &Speak
or Box<Speak>
are called trait objects.