I recently started learning rust and was watching a video about traits and I learned traits were also valid types if dynamically dispatched. What is the point of having a variable with a trait as a type if it has the costs of
struct Animal;
trait Roars {
fn roar(&self);
}
//implement trait roar
impl Roars for Animal {
fn roar(&self) {
println!("roarrrrrr")
}
}
//implement a method rawr
impl Animal {
fn rawr(&self) {
println!("rawrrrrrrrrr")
}
}
fn main() {
let lion: Box<dyn Roars> = Box::new(Animal);
let cheeta: Animal = Animal;
lion.roar();
cheeta.rawr()
}
>>>roarrrrrr
>>>rawrrrrrrrrr
I tried looking all over google for when this pattern would be a good idea but I couldn't find anything all I know is that it is possible but it comes at a bit of a cost when it comes to code performance so when should i use this pattern?
There are a few places where this pattern is required:
Vec
) whose items need to be heterogeneous, but must have a minimum of functionality to be useful in the container. The canonical examples in software development tend to be a heterogeneous set of callback functions (expressed Box<dyn Fn>
in Rust) or a heterogeneous set of GUI widgets, for example. (What use is a container that can only hold one kind of widget?)impl Future
) until TAIT is stabilized. Until then, those trait methods need to return Box<dyn Future>
.There are other places where this pattern can simplify the code substantially. Erasing types with dyn
can often eliminate generic type parameters, and sometimes simplifying the code is worth the rather minor runtime cost of an additional heap allocation, vtable lookup, and indirection to the data.