Owned Trait Objects
پیشتر دیدیم که چگونه میتوان ازویژگی اشیاء (trait objects) با ارجاعات استفاده کرد، مثلاً dyn Pet&
. با این حال، میتوانیم از اشیاء ویژگی با اشارهگرهای هوشمند مانند Box
نیز استفاده کنیم تا یک شیء ویژگی مالک (owned trait object) ایجاد کنیم: <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!(" Woof، نام من {} است!", 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("Fido"), age: 5 }), ]; for pet in pets { println!("سلام، شما کی هستید؟ {}", pet.talk()); } }
چیدمان حافظه پس از تخصیص pets
:
This slide should take about 10 minutes.
- تایپهایی که ویژگی معین را پیادهسازی میکنند ممکن است اندازههای مختلفی داشته باشند. این موضوع باعث میشود که داشتن مواردی مانند
<Vec<dyn Pet
در مثال بالا غیرممکن باشد. dyn Pet
راهی است برای اطلاع دادن به کامپایلر درباره یک تایپ با اندازه پویا که ویژگیPet
را پیادهسازی میکند.- در این مثال،
pets
در stack تخصیص داده میشود و دادههای vector در heap هستند. دو عنصر vector اشارهگرهای چاق (fat pointers) هستند:- اشارهگر چاق (fat pointer) یک اشارهگر با عرض دو برابر است. این اشارهگر دو مؤلفه دارد: یک اشارهگر به شیء واقعی و یک اشارهگر به روشهای جدول مجازی (vtable) برای پیادهسازی
Pet
آن شیء خاص. - دادههای مربوط به
Dog
به نام Fido شامل فیلدهایname
وage
است.Cat
دارای فیلدlives
است.
- اشارهگر چاق (fat pointer) یک اشارهگر با عرض دو برابر است. این اشارهگر دو مؤلفه دارد: یک اشارهگر به شیء واقعی و یک اشارهگر به روشهای جدول مجازی (vtable) برای پیادهسازی
- خروجیهای زیر را در مثال بالا مقایسه کنید:
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>>());