Rust
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.
Örnek çözümü göster
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));
}
Kendini test et
-
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)
- Hayır
- Yalnızca Box ile
Cevabı göster
Evet; &Kedi otomatik olarak &dyn Ses'e dönüşür (unsize coercion) — Derleyici dönüşümde vtable işaretçisini ekler; ters yön (dyn → somut) Any ile downcast gerektirir.
-
Statik dağıtım
fn statik____(x: &T) -> String {
x.ses()
}
Cevabı göster
fn statik<T: Ses>(x: &T) -> String {
x.ses()
}
-
Dağıtım ve özelliği
- 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
Sıradaki ders: Object safety