Objetos Trait
Los objetos de traits permiten valores de diferentes tipos, por ejemplo, en una colección:
trait Pet { fn name(&self) -> String; } struct Dog { name: String, } struct Cat; impl Pet for Dog { fn name(&self) -> String { self.name.clone() } } impl Pet for Cat { fn name(&self) -> String { String::from("The cat") // No name, cats won't respond to it anyway. } } fn main() { let pets: Vec<Box<dyn Pet>> = vec![ Box::new(Cat), Box::new(Dog { name: String::from("Fido") }), ]; for pet in pets { println!("Hello {}!", pet.name()); } }
Diseño de la memoria después de asignar pets
:
- Los tipos que implementan un trait determinado pueden tener diferentes tamaños. Esto hace imposible tener elementos como
Vec<Pet>
en el ejemplo anterior. dyn Pet
es una forma de indicar al compilador un tipo de tamaño dinámico que implementaPet
.- En el ejemplo,
pets
contiene punteros grandes en los objetos que implementanPet
. El puntero grande consta de dos componentes: un puntero al objeto real y un puntero a la tabla de métodos virtuales para la implementación dePet
en ese objeto concreto. - Compara estas salidas en el ejemplo anterior:
println!("{} {}", std::mem::size_of::<Dog>(), std::mem::size_of::<Cat>()); println!("{} {}", std::mem::size_of::<&Dog>(), std::mem::size_of::<&Cat>()); println!("{}", std::mem::size_of::<&dyn Pet>()); println!("{}", std::mem::size_of::<Box<dyn Pet>>());