CodeBlanks Logo Icon CodeBlanks

dyn Trait

dyn Trait ile dinamik dağıtım yapılan trait nesnesini öğrenirsin.

dyn Trait

Farklı türleri aynı koleksiyonda tutmak gerektiğinde generic'ler yetmez, çünkü Vec<T> tek bir T ister. Trait nesnesi (dyn Trait) bunu çözer; metot çağrısı çalışma anında bir tablo (vtable) üzerinden yapılır:

let sekiller: Vec<Box<dyn Sekil>> = vec![
    Box::new(Kare(2.0)),
    Box::new(Daire(1.0)),
];
for s in &sekiller {
    println!("{}: {:.2}", s.ad(), s.alan());
}

dyn Trait'in boyutu derleme anında bilinmez; bu yüzden her zaman bir işaretçi arkasında kullanılır: Box<dyn T>, &dyn T, Rc<dyn T>.

Nesne güvenliği

Her trait dyn ile kullanılamaz. Trait nesnesi olabilmesi için metotlarının Self döndürmemesi ve generic tür parametresi almaması gerekir. Örneğin Clone (fn clone(&self) -> Self) nesne güvenli değildir:

// let v: Vec<Box<dyn Clone>>;   // hata E0038
let v: Vec<Box<dyn std::fmt::Display>> = vec![Box::new(5), Box::new("beş")];
for x in &v { print!("{x} "); }   // 5 beş

Uygulama Şekil listesi

ad ve alan metotlu Sekil trait'ini Kare(f64) ve Daire(f64) için uygula. Vec<Box<dyn Sekil>> içinde Kare(2.0) ve Daire(1.0) tut; her birini ad: alan ({:.2}) biçiminde, sonra toplam: X yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
trait Sekil {
    fn alan(&self) -> f64;
    fn ad(&self) -> String;
}

struct Kare(f64);
struct Daire(f64);

impl Sekil for Kare {
    fn alan(&self) -> f64 {
        self.0 * self.0
    }
    fn ad(&self) -> String {
        String::from("kare")
    }
}

impl Sekil for Daire {
    fn alan(&self) -> f64 {
        std::f64::consts::PI * self.0 * self.0
    }
    fn ad(&self) -> String {
        String::from("daire")
    }
}

fn main() {
    let sekiller: Vec<Box<dyn Sekil>> = vec![Box::new(Kare(2.0)), Box::new(Daire(1.0))];
    let mut toplam = 0.0;
    for s in &sekiller {
        println!("{}: {:.2}", s.ad(), s.alan());
        toplam += s.alan();
    }
    println!("toplam: {:.2}", toplam);
}

Beklenen çıktı

kare: 4.00
daire: 3.14
toplam: 7.14

Soru ve cevaplar

Dersin sorularını cevaplarıyla birlikte inceleyebilirsin. Kendini denemek istersen dersi interaktif olarak çöz.

1 Statik dağıtım (generic) ile dinamik dağıtım (dyn) arasındaki temel ödünleşim nedir?

  • Fark yok
  • Generic daha hızlı ama tek tür; dyn esnek ama küçük bir çalışma anı maliyeti var Doğru cevap
  • dyn her zaman daha hızlı
  • Generic çalışma anında çözülür

Açıklama: Generic kod satır içine alınabilir (inline); dyn çağrısı işaretçi üzerinden dolaylıdır ve satır içine alınamaz.

2 Trait nesnesi

Soru
let sekiller: Vec<Box<____ Sekil>> = vec![Box::new(Kare(2.0))];
Cevap
let sekiller: Vec<Box<dyn Sekil>> = vec![Box::new(Kare(2.0))];

Açıklama: dyn Sekil, Sekil uygulayan herhangi bir türü çalışma anında temsil eder.

3 Tür ve dağıtım

Kavram Anlamı
fn f<T: Sekil>(x: &T) Statik
fn f(x: &dyn Sekil) Dinamik
Vec<Box<dyn Sekil>> Karışık türler
Box<dyn Clone> E0038

Orta seviye bölümündeki tüm dersler