Genelleştirilmiş (Generic) Veri Türleri

Belirli alan türü (concrete field type) üzerinde soyutlama yapmak için genelleştirmeleri (generics) kullanabilirsiniz. Önceki bölümün alıştırmasına geri dönersek:

pub trait Logger {
    /// Belirtilen ayrıntı seviyesinde bir mesaj kaydedin.
    fn log(&self, verbosity: u8, message: &str);
}

struct StderrLogger;

impl Logger for StderrLogger {
    fn log(&self, verbosity: u8, message: &str) {
        eprintln!("ayrıntı seviyesi={verbosity}: {message}");
    }
}

/// Yalnızca belirtilen ayrıntı seviyesine kadar olan mesajları kaydedin.
struct VerbosityFilter<L> {
    max_verbosity: u8,
    inner: L,
}

impl<L: Logger> Logger for VerbosityFilter<L> {
    fn log(&self, verbosity: u8, message: &str) {
        if verbosity <= self.max_verbosity {
            self.inner.log(verbosity, message);
        }
    }
}

fn main() {
    let logger = VerbosityFilter { max_verbosity: 3, inner: StderrLogger };
    logger.log(5, "Bilginiz Olsun");
    logger.log(2, "Eyvah");
}
This slide should take about 10 minutes.
  • S: Neden L, impl<L: Logger> .. VerbosityFilter<L>’de iki kez belirtiliyor? Bu gereksiz (redundant) değil mi?
    • Bunun nedeni, genelleştirilmiş (generic) tür için genel bir gerçekleştirme bölümü (generic implementation section) olmasıdır. Onlar, bağımsız olarak genelleştirilmiştir (generic).
    • Bu, bu metotların herhangi bir L için tanımlandığı anlamına gelir.
    • impl VerbosityFilter<StderrLogger> { .. } yazmak mümkündür.
      • VerbosityFilter hala genelleştirilmiştir türdür ve VerbosityFilter<f64> türünü kullanabilirsiniz, ancak bu bloktaki metotlar yalnızca VerbosityFilter<StderrLogger> için mevcut olacaktır.
  • VerbosityFilter türünün kendisine bir özellik sınırı (trait bound)koymadığımıza dikkat edin. Oraya da sınırlar koyabilirsiniz, ancak genellikle Rust’ta özellik sınırlarını (trait bounds) yalnızca impl bloklarına koyarız.