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 veVerbosityFilter<f64>
türünü kullanabilirsiniz, ancak bu bloktaki metotlar yalnızcaVerbosityFilter<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ızcaimpl
bloklarına koyarız.