capypad
0 Tage Serie
rust / intermediate
Snippet

Innere Veranderlichkeit mit RefCell<T>

RefCell<T> ermoglicht innere Veranderlichkeit, indem die Borrow-Prufung von der Kompilierzeit zur Laufzeit verschoben wird. Wahrend eine &self Referenz normalerweise Veranderung verhindert, erlaubt RefCell die Mutation der enthaltenen Daten. Die borrow_mut() Methode gibt eine mutable Referenz zuruck, und RefCell verfolgt, wie viele Borrows aktiv sind. Wenn Sie versuchen, die Borrow-Regeln zur Laufzeit zu verletzen, panic das Programm. Dieses Muster ist nutzlich, wenn Sie Daten in Szenarien verandern mussen, in denen Unveranderlichkeit erwartet wird.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
use std::cell::RefCell;
 
struct Logger {
messages: RefCell<Vec<String>>,
max_size: usize,
}
 
impl Logger {
fn new(max_size: usize) -> Self {
Self {
messages: RefCell::new(Vec::new()),
max_size,
}
}
 
fn log(&self, msg: &str) {
let mut messages = self.messages.borrow_mut();
if messages.len() >= self.max_size {
messages.remove(0);
}
messages.push(msg.to_string());
}
 
fn get_messages(&self) -> Vec<String> {
self.messages.borrow().clone()
}
}
 
fn main() {
let logger = Logger::new(3);
logger.log("Application started");
logger.log("User logged in");
logger.log("Data loaded");
logger.log("Request processed");
 
println!("Logged messages: {:?}", logger.get_messages());
}
Erklärung
1
use std::cell::RefCell;
Importiere RefCell aus dem std::cell Modul, das Primitive fur innere Veranderlichkeit bereitstellt
2
struct Logger {
Definiere eine Logger Struct, die veranderbare Daten hinter einer unveranderlichen Schnittstelle halt
3
messages: RefCell<Vec<String>>,
Verwende RefCell um den Vec zu wrappen und ermogliche Mutation durch shared Referenzen
4
max_size: usize,
Speichere die maximale Kapazitat fur den Log-Puffer
5
fn new(max_size: usize) -> Self {
Konstruktor erstellt einen neuen Logger mit angegebener Puffergröße
6
messages: RefCell::new(Vec::new()),
Initialisiere das RefCell mit einem leeren Vec darin
7
fn log(&self, msg: &str) {
Methode nimmt immutable self aber kann interne Daten andern dank RefCell
8
let mut messages = self.messages.borrow_mut();
Erwerbe mutable Borrow des inneren Vec; hier findet die Laufzeit-Borrow-Prüfung statt
9
if messages.len() >= self.max_size {
Prüfe ob Puffer die maximale Kapazität erreicht hat
10
messages.remove(0);
Entferne alteste Nachricht bei Kapazitat (FIFO-Verhalten)
11
messages.push(msg.to_string());
Fuge neue Nachricht am Ende des Puffers hinzu
12
fn get_messages(&self) -> Vec<String> {
Getter-Methode um alle protokollierten Nachrichten abzurufen
13
self.messages.borrow().clone()
Immutable Borrow, klone um eigene Daten zuruckzugeben