Statik ve dinamik dağıtım
- Rust kursu
- İleri seviye
- Ders 56/81
- 4 dk
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
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
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>&dyn Ses</code> alıyorsa ona <code>&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
fn statik____(x: &T) -> String {
x.ses()
}
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 |