CodeBlanks Logo Icon CodeBlanks

&dyn Trait

&dyn Trait ile referans tabanlı dağıtım yaparsın.

&dyn Trait

Trait nesnesinin sahiplik gerektirmeyen biçimi ödünç &dyn Trait ve &mut dyn Trait'tir. Heap ayırması yoktur; generic'e göre avantajı, fonksiyonun tek bir kopyasının derlenmesidir. Standart kütüphane bunu G/Ç için sık kullanır:

use std::io::Write;

fn yaz(w: &mut dyn Write, mesaj: &str) -> std::io::Result<()> {
    writeln!(w, "{mesaj}")
}

let mut tampon: Vec<u8> = Vec::new();
yaz(&mut tampon, "merhaba")?;           // belleğe
yaz(&mut std::io::stdout(), "merhaba")?; // ekrana

Aynı fonksiyon dosya, soket ya da bellek tamponuyla çalışır.

Ömürlü trait nesneleri

Trait nesnelerinin de bir ömrü vardır. Box<dyn Trait> varsayılan olarak Box<dyn Trait + 'static>'tir; ödünç veri tutan bir türü kutulamak için ömrü açıkça yazmak gerekir:

struct Bakis<'a>(&'a str);
impl Ses for Bakis<'_> {
    fn ses(&self) -> String { self.0.to_string() }
}

fn kutula<'a>(s: &'a str) -> Box<dyn Ses + 'a> {
    Box::new(Bakis(s))
}

Uygulama Hedeften bağımsız yazma

Yukarıdaki yaz fonksiyonunu yaz. Bir Vec<u8> tamponuna merhaba yaz; tamponu metne çevirip merhaba (8 bayt) biçiminde yazdır.

Başlangıç kodu

main.rs
use std::io::{self, Write};

fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
use std::io::{self, Write};

fn yaz(w: &mut dyn Write, mesaj: &str) -> io::Result<()> {
    writeln!(w, "{mesaj}")
}

fn main() -> io::Result<()> {
    let mut tampon: Vec<u8> = Vec::new();
    yaz(&mut tampon, "merhaba")?;
    let metin = String::from_utf8_lossy(&tampon);
    println!("{} ({} bayt)", metin.trim(), tampon.len());
    Ok(())
}

Beklenen çıktı

merhaba (8 bayt)

Soru ve cevaplar

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

1 <code>&amp;dyn Write</code> yerine <code>&amp;mut dyn Write</code> neden gerekir?

  • Gerekmez
  • Daha hızlıdır
  • dyn ile & kullanılamaz
  • Write::write_all &mut self alır; yazmak hedefi değiştirir Doğru cevap

Açıklama: Trait nesnesi de metotların self biçimine uymalıdır; &dyn yalnızca &self metotlarını çağırabilir.

2 Değiştirilebilir trait nesnesi

Soru
fn yaz(w: &____ dyn Write, mesaj: &str) -> std::io::Result<()> {
    writeln!(w, "{mesaj}")
}
Cevap
fn yaz(w: &mut dyn Write, mesaj: &str) -> std::io::Result<()> {
    writeln!(w, "{mesaj}")
}

Açıklama: Write metotları &mut self aldığı için &mut dyn Write gerekir.

3 Biçim ve özelliği

Kavram Anlamı
&dyn T Ödünç, salt okuma
&mut dyn T Ödünç, değiştirir
Box<dyn T> Sahip, 'static
Box<dyn T + 'a> Ödünç veri tutabilir

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