dyn Trait
Rust, genelleştirmeler (generics) yoluyla statik yönlendirme (static dispatch) için özellikleri (trait) kullanmaya ek olarak, özellik nesneleri (trait objects) yoluyla silinmiş türle (type-erased), dinamik yönlendirmeyi (dynamic dispatch) destekler:
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!("Hav, benim adım {}!", self.name) } } impl Pet for Cat { fn talk(&self) -> String { String::from("Miyav!") } } // Genelleştirmeleri (generics) ve statik yönlendirmeyi (static dispatch) kullanır. fn generic(pet: &impl Pet) { println!("Merhaba, nasılsın? {}", pet.talk()); } // Tür silmeyi (type-erasure) ve dinamik yönlendirmeyi (dynamic dispatch) kullanır. fn dynamic(pet: &dyn Pet) { println!("Merhaba, nasılsın? {}", pet.talk()); } fn main() { let cat = Cat { lives: 9 }; let dog = Dog { name: String::from("Fido"), age: 5 }; generic(&cat); generic(&dog); dynamic(&cat); dynamic(&dog); }
-
impl Traitde dahil olmak üzere genelleştirmeler (generics), genelleştirmenin oluşturulduğu her farklı tür için fonksiyonun özel bir örneğini oluşturmak üzere tek biçimli hâle getirmeyi (monomorphization) kullanır. Bu, genelleştirilmiş bir fonksiyon içinden bir özellik (trait) metodunu çağırmanın hala statik yönlendirme (static dispatch) kullandığı anlamına gelir, çünkü derleyici tam tür bilgisine sahiptir ve hangi türün özellik gerçekleştiriminin (trait implementation) kullanılacağını çözebilir. -
dyn Traitkullanırken, bunun yerine bir sanal metot tablosu (virtual method table) (vtable) aracılığıyla dinamik yönlendirme (dynamic dispatch) kullanır. Bu, hangi türdePetgeçirilirse geçirilsin kullanılan tek birfn dynamicsürümü olduğu anlamına gelir. -
dyn Traitkullanırken, özellik nesnesinin (trait object) bir tür dolaylı yol (indirection) arkasında olması gerekir. Bu durumda bu bir referanstır, ancakBoxgibi akıllı gösterici (smart pointer) türleri de kullanılabilir (bu 3. günde gösterilecektir). -
Çalışma zamanında, bir
&dyn Pet, “genişletilmiş bir gösterici (fat pointer)” olarak temsil edilir, yani iki göstericiden oluşan bir çift: Bir gösterici,Pet’i gerçekleştiren (implement) belirli nesneye işaret eder ve diğeri o tür için özellik gerçekleştiriminin (trait implementation) sanal metot tablosuna (vtable) işaret eder.&dyn Petüzerindetalkmetodunu çağırırken, derleyici sanal metot tablosundatalkiçin fonksiyon göstericisini (function pointer) arar ve ardındanDogveyaCat’e göstericiyi o fonksiyona geçirerek fonksiyonu çağırır. Derleyicinin bunu yapmak içinPet’in belirli olan türünü (concrete type) bilmesi gerekmez. -
Bir
dyn Trait, “silinmiş tür (type-erased)” olarak kabul edilir, çünkü artık somut türün ne olduğuna dair derleme zamanı bilgisine sahip değiliz.