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
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