Setter
Teil des Abschnitts Object Oriented Programming der Rust-Journey von Coddy — Lektion 12 von 61.
Getter ermöglichen es externem Code, private Daten zu lesen. Aber was ist, wenn Sie zulassen müssen, dass dieser sie ändert? Hier kommen Setter-Methoden ins Spiel – öffentliche Methoden, die private Felder auf kontrollierte Weise ändern.
Ein einfacher Setter nimmt &mut self und einen neuen Wert entgegen:
// wallet.rs
pub struct Wallet {
balance: f64,
}
impl Wallet {
pub fn new(initial: f64) -> Wallet {
Self { balance: initial }
}
pub fn balance(&self) -> f64 {
self.balance
}
pub fn set_balance(&mut self, amount: f64) {
self.balance = amount;
}
}
Im Gegensatz zu Gettern verwenden Rust-Setter normalerweise das Präfix set_, um deutlich anzuzeigen, dass sie Daten ändern. Der Parameter &mut self ist essenziell – er erteilt der Methode die Erlaubnis, die Felder des Structs zu ändern.
Die wahre Stärke von Settern ist die Validierung. Anstatt blind jeden Wert zu akzeptieren, können Sie Regeln erzwingen:
pub fn set_balance(&mut self, amount: f64) {
if amount >= 0.0 {
self.balance = amount;
}
// Negative Werte werden stillschweigend ignoriert
}
Jetzt schützt sich das Wallet selbst – egal welchen Wert externer Code zu setzen versucht, der Kontostand kann niemals negativ werden. Das ist Kapselung in Aktion: Das Struct kontrolliert seine eigenen Invarianten, und externer Code kann es schlichtweg nicht in einen ungültigen Zustand versetzen.
Aufgabe
EinfachLassen Sie uns ein Thermostatsystem bauen, das zeigt, wie Setter Regeln erzwingen können, um Daten valide zu halten. Ihr Thermostat wird eine Temperatureinstellung haben, die nur innerhalb eines sicheren Bereichs angepasst werden kann.
Sie werden zwei Dateien erstellen, um Ihren Code zu organisieren:
thermostat.rs: Definieren Sie einThermostatStruct mit einem privatentemperatureFeld (i32). Das Struct sollte öffentlich sein, aber das Feld bleibt privat, um es vor ungültigen Werten zu schützen. Implementieren Sie:- Einen
newKonstruktor, der eine Anfangstemperatur entgegennimmt - Einen
temperatureGetter, der die aktuelle Temperatur zurückgibt - Einen
set_temperatureSetter, der nur Werte zwischen 10 und 30 (einschließlich) akzeptiert. Wenn der Wert außerhalb dieses Bereichs liegt, sollte die Temperatur unverändert bleiben.
- Einen
main.rs: Binden Sie Ihr Thermostat-Modul ein, erstellen Sie einen Thermostat und demonstrieren Sie die Validierung des Setters, indem Sie versuchen, verschiedene Temperaturen einzustellen und das Ergebnis nach jedem Versuch ausgeben.
Der Setter sollte ungültige Werte stillschweigend ignorieren – keine Fehlermeldungen, behalten Sie einfach die aktuelle Temperatur unverändert bei, wenn jemand versucht, sie außerhalb des gültigen Bereichs einzustellen.
Ihre Ausgabe sollte genau diesem Format folgen:
Initial: {temperature}
After setting to {attempted_value}: {temperature}
After setting to {attempted_value}: {temperature}Wenn Sie zum Beispiel einen Thermostat bei 20 erstellen und dann versuchen, ihn auf 25 (gültig) und dann auf 50 (ungültig) einzustellen, wäre die Ausgabe:
Initial: 20
After setting to 25: 25
After setting to 50: 25Sie erhalten drei Eingaben: die Anfangstemperatur, die erste zu versuchende Temperatur und die zweite zu versuchende Temperatur.
Spickzettel
Setter-Methoden ermöglichen es externem Code, private Felder auf kontrollierte Weise zu ändern. Sie nehmen &mut self entgegen, um die Erlaubnis zu erhalten, die Daten des Structs zu ändern.
Grundlegende Setter-Syntax:
pub fn set_balance(&mut self, amount: f64) {
self.balance = amount;
}Rust-Setter verwenden normalerweise das Präfix set_, um deutlich anzuzeigen, dass sie Daten ändern.
Setter ermöglichen eine Validierung, um Regeln durchzusetzen und die Datenintegrität zu wahren:
pub fn set_balance(&mut self, amount: f64) {
if amount >= 0.0 {
self.balance = amount;
}
// Ungültige Werte werden stillschweigend ignoriert
}Dies ist Kapselung in Aktion: Das Struct kontrolliert seine eigenen Invarianten und verhindert, dass externer Code es in einen ungültigen Zustand versetzt.
Probier es selbst
mod thermostat;
use thermostat::Thermostat;
fn main() {
// Eingaben lesen
let mut input1 = String::new();
std::io::stdin().read_line(&mut input1).expect("Failed to read line");
let initial_temp: i32 = input1.trim().parse().expect("Invalid number");
let mut input2 = String::new();
std::io::stdin().read_line(&mut input2).expect("Failed to read line");
let first_attempt: i32 = input2.trim().parse().expect("Invalid number");
let mut input3 = String::new();
std::io::stdin().read_line(&mut input3).expect("Failed to read line");
let second_attempt: i32 = input3.trim().parse().expect("Invalid number");
// TODO: Erstelle ein Thermostat mit der Anfangstemperatur
// TODO: Gib die Anfangstemperatur aus
// Format: "Initial: {temperature}"
// TODO: Versuche, die erste Temperatur einzustellen und gib das Ergebnis aus
// Format: "After setting to {attempted_value}: {temperature}"
// TODO: Versuche, die zweite Temperatur einzustellen und gib das Ergebnis aus
// Format: "After setting to {attempted_value}: {temperature}"
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Object Oriented Programming
1Methoden und Verhalten
Einführung in ImplementierungsblöckeDer Self-ParameterVeränderliche MethodenAssoziierte FunktionenMehrere ImplementierungsblöckeMethod ChainingRückblick – Rechteck-Aktionen4Projekt: Virtuelles Haustier
Das Haustier definierenDas Haustier füttern7Standard-Traits
Das Debug-TraitDas Display-TraitClone und CopyGleichheits-TraitsZusammenfassung – Druckbarer Punkt10Projekt: Dokumentensystem
Das Draw-TraitText-Komponente2Kapselung und Module
Grundlagen der ModuleDas Public-SchlüsselwortPrivate FelderGetterSetterWiederholung – Sicherer Tresor5Generics
Generische StructsGenerische MethodenMehrere generische TypenGenerische FunktionenZusammenfassung - Koordinatenpunkt8Traits als Einschränkungen
Syntax für Trait BoundsMehrfache BoundsDie Where-KlauselTypen mit Traits zurückgebenRückblick – Generischer Drucker11Design Patterns in Rust
Newtype-PatternKompositionDas Drop-TraitFrom und IntoZusammenfassung – Smart Pointer Mock3Fortgeschrittene Enums
Enums mit DatenMethoden für EnumsMatching von DatenvariantenDas Option-Enum erneut betrachtetZusammenfassung – Shape-Enum6Definition von Traits
Was ist ein Trait?Traits implementierenStandardimplementierungenStandardimplementierungen überschreibenTraits mit ParameternZusammenfassung – Media Player