Objetos Trait
Objetos trait permitem valores de diferentes tipos, por exemplo, em uma coleção:
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("Gato") // Sem nomes, gatos não respondem mesmo. } } fn main() { let pets: Vec<Box<dyn Pet>> = vec![ Box::new(Cat), Box::new(Dog { name: String::from("Bidu") }), ]; for pet in pets { println!("Olá {}!", pet.name()); } }
Layout da memória após alocar pets:
- Tipos que implementam um dado
traitpodem ter tamanhos diferentes. Isto torna impossível haver coisas comoVec<Pet>no exemplo anterior. dyn Peté uma maneira de dizer ao compilador sobre um tipo de tamanho dinâmico que implementaPet.- No exemplo,
petspossui fat pointers para objetos que implementamPet. O fat pointer consiste em dois componentes, um ponteiro para o objeto propriamente dito e um ponteiro para a tabela de métodos virtuais para a implementação dePetdo objeto em particular. - Compare estas saídas no exemplo 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>>());