Objetos de Trait ProprietĂĄrios
Anteriormente vimos como objetos de trait podem ser usados com referĂȘncias, por exemplo, &dyn Pet
. No entanto, também podemos usar objetos de trait com ponteiros inteligentes como Box
para criar um objeto de trait owned: Box<dyn Pet>
.
struct Dog { name: String, age: i8, } struct Cat { lives: i8, } trait Pet { fn talk(&self) -> String; } impl Pet for Dog { fn talk(&self) -> String { format!("Auau, meu nome Ă© {}", self.name) } } impl Pet for Cat { fn talk(&self) -> String { String::from("Miau!") } } fn main() { let pets: Vec<Box<dyn Pet>> = vec![ Box::new(Cat { lives: 9 }), Box::new(Dog { name: String::from("Bidu"), age: 5 }), ]; for pet in pets { println!("OlĂĄ, quem Ă© vocĂȘ? {}", pet.talk()); } }
Layout da memĂłria apĂłs alocar pets
:
This slide should take about 10 minutes.
- Tipos que implementam um dado
trait
podem ter tamanhos diferentes. Isto torna impossĂvel haver coisas comoVec<dyn Pet>
no exemplo anterior. dyn Pet
Ă© uma maneira de dizer ao compilador sobre um tipo de tamanho dinĂąmico que implementaPet
.- No exemplo,
pets
é alocado na pilha e os dados do vetor estão no heap. Os dois elementos do vetor são fat pointers (ponteiros "gordos"):- Um fat pointer é um ponteiro de dupla largura. Ele tem dois componentes: um ponteiro para o objeto real e um ponteiro para a tabela de métodos virtuais (vtable) para a implementação
Pet
desse objeto em particular. - Os dados para o
Dog
chamado Fido sĂŁo os camposname
eage
. OCat
tem um campolives
.
- Um fat pointer é um ponteiro de dupla largura. Ele tem dois componentes: um ponteiro para o objeto real e um ponteiro para a tabela de métodos virtuais (vtable) para a implementação
- 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>>());