Objetos Trait
Objetos trait
permitem valores de diferentes tipos, por exemplo, em uma coleção:
trait Pet { fn nome(&self) -> String; } struct Cachorro { nome: String, } struct Gato; impl Pet for Cachorro { fn nome(&self) -> String { self.nome.clone() } } impl Pet for Gato { fn nome(&self) -> String { String::from("O gato") // Sem nomes, de qualquer forma gatos não reconhecem. } } fn main() { let pets: Vec<Box<dyn Pet>> = vec![ Box::new(Gato), Box::new(Cachorro { nome: String::from("Bidu") }), ]; for pet in pets { println!("Olá {}!", pet.nome()); } }
Layout da memória após alocar pets
:
- Tipos que implementam um dado
trait
podem 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,
pets
possui 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 dePet
do objeto em particular. - Compare estas saídas no exemplo anterior::
println!("{} {}", std::mem::size_of::<Cachorro>(), std::mem::size_of::<Gato>()); println!("{} {}", std::mem::size_of::<&Cachorro>(), std::mem::size_of::<&Gato>()); println!("{}", std::mem::size_of::<&dyn Pet>()); println!("{}", std::mem::size_of::<Box<dyn Pet>>());