dyn Trait
- Rust kursu
- Orta seviye
- Ders 23/115
- 4 dk
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
fn main() {
// buraya yaz
}Örnek çözüm
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
let sekiller: Vec<Box<____ Sekil>> = vec![Box::new(Kare(2.0))];
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 |