traits that can be used in dynamic assignments are called trait objects, which are represented as dyn traits. traits have different meanings than interfaces in the object-oriented world, and not all traits can be used for polymorphism. the following two traits cannot be used for polymorphism:
- Clone cannot be converted to a trait object because the clone method returns Self. If there is a method capable of accepting dyn Clone parameters, when calling the clone method because the clone method returns Self, the compiler I can’t know the specific return type.
pub trait Clone {
fn clone(&self) -> Self;
fn clone_from(&mut self, source: &Self) { ... }
}
copy the code
- Extend trait cannot be used as a trait object because extend methods have generic parameters. If we call the extend method, there are multiple extend addresses in the virtual method table, and we have no way of knowing which one to call.
traits that are not object-safe cannot
pub trait Extend<A> {
fn extend<T>(&mut self, iter: T)
where
T: IntoIterator<Item = A>;
fn extend_one(&mut self, item: A) { ... }
fn extend_reserve(&mut self, additional: usize) { ... }
}
copy the code
A trait that can be used as a trait object is called an object-safe trait. An object-safe trait where the method cannot take generic parameters, or use the Self type. In addition, object-safe traits cannot have static methods (the first argument cannot be dereferenced to Self)
Traits that use the Self:Sized constraint cannot be used as trait objects. You can constrain Self:Sized to a method of trait that cannot be used for dynamic assignment, but the trait itself is object-safe. If a method of trait has generic parameters, you can take the method with a Self:Sized constraint to preserve the object security of the trait.
if you implement a trait type of kind, consider preserving the object security of the trait.