CodeBlanks Logo Icon CodeBlanks

Generic yapı

Kitap modelini generic yapıya çevirirsin.

Generic yapı

Kitapları tutacak bir Raf yazalım. Rafı generic yapmak, aynı kodu ileride dergi ya da film için de kullanmayı sağlar:

pub struct Raf<T> {
    ogeler: Vec<T>,
}

impl<T> Raf<T> {
    pub fn new() -> Self { Self { ogeler: Vec::new() } }
    pub fn ekle(&mut self, x: T) { self.ogeler.push(x); }
    pub fn len(&self) -> usize { self.ogeler.len() }
}

Vec gizli kaldığı için rafın iç yapısını ileride (örneğin BTreeMap'e) değiştirmek kullanıcıyı etkilemez.

Default uygulamak

Argümansız new sunan türler için Default uygulamak da gelenektir; böylece Raf::default() ve ..Default::default() çalışır:

impl<T> Default for Raf<T> {
    fn default() -> Self {
        Self::new()
    }
}

let mut sayilar: Raf<u32> = Raf::default();
sayilar.ekle(7);

Tür çıkarımı sayesinde Raf::new() çoğu zaman tür yazmadan kullanılır: ilk ekle çağrısı T'yi belirler.

Uygulama İki raf

mod kitaplik içinde önceki Kitap ile birlikte generic Raf<T> (new, ekle, len) yaz. Bir kitap rafına iki kitap, bir u32 rafına üç sayı ekle; iki rafın uzunluğunu boşlukla yazdır.

Başlangıç kodu

main.rs
fn main() {
    // buraya yaz
}

Örnek çözüm

main.rs
mod kitaplik {
    pub struct Kitap {
        ad: String,
        yazar: String,
        yil: u16,
    }

    impl Kitap {
        pub fn new(ad: &str, yazar: &str, yil: u16) -> Self {
            Self {
                ad: ad.to_string(),
                yazar: yazar.to_string(),
                yil,
            }
        }
        pub fn ad(&self) -> &str {
            &self.ad
        }
        pub fn yil(&self) -> u16 {
            self.yil
        }
    }

    pub struct Raf<T> {
        ogeler: Vec<T>,
    }

    impl<T> Raf<T> {
        pub fn new() -> Self {
            Self { ogeler: Vec::new() }
        }
        pub fn ekle(&mut self, x: T) {
            self.ogeler.push(x);
        }
        pub fn len(&self) -> usize {
            self.ogeler.len()
        }
    }
}

use kitaplik::{Kitap, Raf};

fn main() {
    let mut kitaplar = Raf::new();
    kitaplar.ekle(Kitap::new("Tutunamayanlar", "Oğuz Atay", 1972));
    kitaplar.ekle(Kitap::new("Kürk Mantolu Madonna", "Sabahattin Ali", 1943));
    let mut sayilar: Raf<u32> = Raf::new();
    for n in [1, 2, 3] {
        sayilar.ekle(n);
    }
    println!("{} {}", kitaplar.len(), sayilar.len());
}

Beklenen çıktı

2 3

Soru ve cevaplar

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

1 Clippy, <code>pub fn len</code> olan bir türe ne önerir?

  • Hiçbir şey
  • pub fn is_empty de eklemeyi Doğru cevap
  • len'i kaldırmayı
  • len'i size yapmayı

Açıklama: len_without_is_empty uyarısı: koleksiyon benzeri türlerde is_empty beklenen bir API'dir.

2 Generic impl

Soru
impl____ Raf<T> {
    pub fn ekle(&mut self, x: T) {
        self.ogeler.push(x);
    }
}
Cevap
impl<T> Raf<T> {
    pub fn ekle(&mut self, x: T) {
        self.ogeler.push(x);
    }
}

Açıklama: Her T için geçerli metotlar impl<T> bloğuna yazılır.

3 İfade ve T

Kavram Anlamı
Raf<Kitap> Kitap rafı
Raf<u32> Sayı rafı
Raf::new() + ekle("a") Raf<&str>
Raf::<f64>::default() Boş f64 rafı

Orta seviye bölümündeki tüm dersler