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 Trait
de 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 Trait
kullanırken, bunun yerine bir sanal metot tablosu (virtual method table) (vtable) aracılığıyla dinamik yönlendirme (dynamic dispatch) kullanır. Bu, hangi türdePet
geçirilirse geçirilsin kullanılan tek birfn dynamic
sürümü olduğu anlamına gelir. -
dyn Trait
kullanırken, özellik nesnesinin (trait object) bir tür dolaylı yol (indirection) arkasında olması gerekir. Bu durumda bu bir referanstır, ancakBox
gibi 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
üzerindetalk
metodunu çağırırken, derleyici sanal metot tablosundatalk
için fonksiyon göstericisini (function pointer) arar ve ardındanDog
veyaCat
’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.