When writing code with traits you can put the trait in a trait bound:
use std::fmt::Debug;
fn myfunction1<T: Debug>(v: Box<T>) {
println!("{:?}", v);
}
fn myfunction2<T: Debug>(v: &T) {
println!("{:?}", v);
}
fn main() {
myfunction1(Box::new(5));
myfunction2(&5);
}
Or directly in a Box
or reference type:
use std::fmt::Debug;
fn myfunction3(v: Box<Debug>) {
println!("{:?}", v);
}
fn myfunction4(v: &Debug) {
println!("{:?}", v);
}
fn main() {
myfunction3(Box::new(5));
myfunction4(&5);
}
These give the same output. So what is the difference?
(This question was inspired by another question where this was just one of several intermingled concepts)
A trait object is an opaque value of another type that implements a set of traits. The set of traits is made up of an object safe base trait plus any number of auto traits. Trait objects implement the base trait, its auto traits, and any supertraits of the base trait.
Dynamic dispatch. Rust provides dynamic dispatch through a feature called 'trait objects'. Trait objects, like &Foo or Box<Foo> , are normal values that store a value of any type that implements the given trait, where the precise type can only be known at runtime.
dyn is a prefix of a trait object's type. The dyn keyword is used to highlight that calls to methods on the associated Trait are dynamically dispatched. To use the trait this way, it must be 'object safe'. Unlike generic parameters or impl Trait , the compiler does not know the concrete type that is being passed.
Importantly, you don't have to put the generic type behind a reference (like &
or Box
), you can accept it directly:
fn myfunction3<T: Debug>(v: T) {
println!("{:?}", v);
}
fn main() {
myfunction3(5);
}
This has the same benefits of monomorphization without the downside of additional memory allocation (Box
) or needing to keep ownership of the value somewhere (&
).
I would say that generics should often be the default choice — you only require a trait object when there is dynamic dispatch / heterogeneity.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With