Rust
Dışarıdan değiştirme
Immutable bir yapıda iç veriyi değiştirme yöntemini öğrenirsin.
Dışarıdan değiştirme
Bir trait metodu &self alıyorsa ve sen uygulamada durum tutman gerekiyorsa (örneğin testte gönderilen mesajları kaydetmek), trait imzasını değiştiremezsin. İç değiştirilebilirlik burada devreye girer:
trait Bildirici {
fn bildir(&self, mesaj: &str);
}
struct Kayitci {
mesajlar: RefCell<Vec<String>>,
}
impl Bildirici for Kayitci {
fn bildir(&self, mesaj: &str) {
self.mesajlar.borrow_mut().push(mesaj.to_string());
}
}
Kullanan kod
Bildirimi kullanan kod yalnızca trait'i bilir ve &dyn Bildirici alır:
fn kota_denetle(b: &dyn Bildirici, yuzde: u32) {
if yuzde > 90 {
b.bildir(&format!("uyarı: {yuzde}"));
}
}
let k = Kayitci { mesajlar: RefCell::new(Vec::new()) };
kota_denetle(&k, 95);
println!("{}", k.mesajlar.borrow().len()); // 1
Gerçek uygulamada Bildirici e-posta gönderir; testte Kayitci mesajları yalnızca saklar.
Uygulama Kayıt tutan bildirici
Yukarıdaki Bildirici, Kayitci ve kota_denetle kodunu yaz. Sırasıyla 95, 50 ve 99 ile çağır; kayıt sayısını ve ilk mesajı boşlukla yazdır.
Örnek çözümü göster
use std::cell::RefCell;
trait Bildirici {
fn bildir(&self, mesaj: &str);
}
struct Kayitci {
mesajlar: RefCell<Vec<String>>,
}
impl Bildirici for Kayitci {
fn bildir(&self, mesaj: &str) {
self.mesajlar.borrow_mut().push(mesaj.to_string());
}
}
fn kota_denetle(b: &dyn Bildirici, yuzde: u32) {
if yuzde > 90 {
b.bildir(&format!("uyarı: {yuzde}"));
}
}
fn main() {
let k = Kayitci { mesajlar: RefCell::new(Vec::new()) };
for y in [95, 50, 99] {
kota_denetle(&k, y);
}
let m = k.mesajlar.borrow();
println!("{} {}", m.len(), m[0]);
}
Kendini test et
-
Bu desen en çok nerede kullanılır?
- Sabitlerde
- Test sahteleri (mock) ve önbellek gibi gizli durum tutan yapılarda
- Her struct alanında
- Thread havuzlarında
Cevabı göster
Test sahteleri (mock) ve önbellek gibi gizli durum tutan yapılarda — Dışarıdan bakınca değişmez görünen ama içeride kayıt tutan yapılar için uygundur.
-
Kaydı sakla
fn bildir(&self, mesaj: &str) {
self.mesajlar.____().push(mesaj.to_string());
}
Cevabı göster
fn bildir(&self, mesaj: &str) {
self.mesajlar.borrow_mut().push(mesaj.to_string());
}
-
Çağrı ve kayıt sayısı
- kota_denetle(&k, 95)
- +1
- kota_denetle(&k, 50)
- Değişmez
- kota_denetle(&k, 91)
- +1 (sınırın üstü)
- kota_denetle(&k, 90)
- Değişmez (sınırda)
Sıradaki ders: Özet - Interior mutability