CodeBlanks Logo Icon CodeBlanks

Statik ve dinamik dağıtım

Statik ve dinamik dağıtım farkını ve maliyetlerini öğrenirsin.

Statik ve dinamik dağıtım

Aynı davranış iki yolla yazılabilir:

fn statik<T: Ses>(x: &T) -> String {   // her T için ayrı kopya
    x.ses()                              // doğrudan, satır içi alınabilir
}

fn dinamik(x: &dyn Ses) -> String {     // tek kopya
    x.ses()                              // vtable üzerinden
}

Statik: daha hızlı çağrı, derleyici satır içine alıp optimize edebilir; bedeli daha büyük ikili ve derleme süresi. Dinamik: tek kod, karışık koleksiyonlar, daha küçük ikili; bedeli dolaylı çağrı ve kaçırılan optimizasyonlar.

Nasıl seçilir?

Varsayılan seçim generic'tir. dyn'e geç: koleksiyonda farklı türler gerekiyorsa, tür çalışma anında belirleniyorsa (eklentiler, yapılandırma), derleme süresi ya da ikili boyutu sorun olmuşsa, ya da API'nin generic parametreyle kirlenmesini istemiyorsan. Performans farkı çoğu uygulamada ölçülemeyecek kadar küçüktür; sıcak döngülerde ölç.

// karışık: generic yetmez
let v: Vec<Box<dyn Ses>> = vec![Box::new(Kedi), Box::new(Kopek)];
// tek tür: generic yeterli
fn hepsi<T: Ses>(v: &[T]) -> Vec<String> { v.iter().map(|x| x.ses()).collect() }

Uygulama İki dağıtım

Yukarıdaki statik ve dinamik fonksiyonlarını yaz. Kedi ile ikisini de çağır ve statik: .. | dinamik: .. biçiminde yazdır.

Başlangıç kodu

main.rs
trait Ses {
    fn ses(&self) -> String;
}

struct Kedi;
struct Kopek;

impl Ses for Kedi {
    fn ses(&self) -> String {
        String::from("Miyav")
    }
}

impl Ses for Kopek {
    fn ses(&self) -> String {
        String::from("Hav")
    }
}

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
trait Ses {
    fn ses(&self) -> String;
}

struct Kedi;
struct Kopek;

impl Ses for Kedi {
    fn ses(&self) -> String {
        String::from("Miyav")
    }
}

impl Ses for Kopek {
    fn ses(&self) -> String {
        String::from("Hav")
    }
}

fn statik<T: Ses>(x: &T) -> String {
    x.ses()
}

fn dinamik(x: &dyn Ses) -> String {
    x.ses()
}

fn main() {
    let k = Kedi;
    println!("statik: {} | dinamik: {}", statik(&k), dinamik(&k));
}

Beklenen çıktı

statik: Miyav | dinamik: Miyav

Soru ve cevaplar

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

1 Bir fonksiyon <code>&amp;dyn Ses</code> alıyorsa ona <code>&amp;Kedi</code> verilebilir mi?

  • as ile
  • Evet; &Kedi otomatik olarak &dyn Ses'e dönüşür (unsize coercion) Doğru cevap
  • Hayır
  • Yalnızca Box ile

Açıklama: Derleyici dönüşümde vtable işaretçisini ekler; ters yön (dyn → somut) Any ile downcast gerektirir.

2 Statik dağıtım

Soru
fn statik____(x: &T) -> String {
    x.ses()
}
Cevap
fn statik<T: Ses>(x: &T) -> String {
    x.ses()
}

Açıklama: Generic sınır, her tür için ayrı bir kopya üreten statik dağıtımdır.

3 Dağıtım ve özelliği

Kavram Anlamı
Statik (generic) Satır içi alınabilir
Dinamik (dyn) Vtable ile çağrı
Monomorfizasyon Tür başına kopya
Unsize coercion &Kedi → &dyn Ses

İleri seviye bölümündeki tüm dersler