Setter
Teil des Abschnitts Objektorientierte Programmierung der Rust-Journey von Coddy. Lektion 12 von 61.
Getter ermöglichen es externem Code, private Daten zu lesen. Aber was, wenn du ihm erlauben musst, sie zu ändern? Hier kommen Setter-Methoden ins Spiel: öffentliche Methoden, die private Felder auf kontrollierte Weise ändern.
Ein grundlegender 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 getter verwenden Rust setter typischerweise das Präfix set_, um eindeutig anzuzeigen, dass sie Daten ändern. Der Parameter &mut self ist wesentlich. Er erteilt der Methode die Berechtigung, die Felder der Struktur zu ändern.
Die eigentliche Stärke von Settern ist die Validierung. Statt jeden Wert blind zu akzeptieren, kannst du Regeln durchsetzen:
pub fn set_balance(&mut self, amount: f64) {
if amount >= 0.0 {
self.balance = amount;
}
// Negative Werte werden stillschweigend ignoriert
}
Jetzt schützt sich die Geldbörse selbst: Unabhängig davon, welchen Wert externer Code zu setzen versucht, kann der balance niemals negativ werden. Das ist Kapselung in Aktion: Die Struktur kontrolliert ihre eigenen Invarianten, und externer Code kann sie einfach nicht in einen ungültigen Zustand versetzen.
Aufgabe
EinfachErstellen wir ein Thermostatsystem, das zeigt, wie Setter Regeln durchsetzen können, um Daten gültig zu halten. Dein Thermostat wird eine Temperatureinstellung haben, die nur innerhalb eines sicheren Bereichs angepasst werden kann.
Du wirst zwei Dateien erstellen, um deinen Code zu organisieren:
thermostat.rs: Definiere eineThermostat-Struktur mit einem privaten Feldtemperature(i32). Die Struktur sollte öffentlich sein, aber das Feld bleibt privat, um es vor ungültigen Werten zu schützen. Implementiere:- Einen
new-Konstruktor, der eine Anfangstemperatur entgegennimmt - Einen
temperature-Getter, der die aktuelle Temperatur zurückgibt - Einen
set_temperature-Setter, 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: Binde dein Thermostatmodul ein, erstelle ein Thermostat und demonstriere die Validierung des Setters, indem du versuchst, verschiedene Temperaturen zu setzen, und nach jedem Versuch das Ergebnis ausgibst.
Der Setter sollte ungültige Werte stillschweigend ignorieren: keine Fehlermeldungen, sondern einfach die aktuelle Temperatur unverändert lassen, wenn jemand versucht, sie außerhalb des gültigen Bereichs zu setzen.
Deine Ausgabe sollte genau diesem Format folgen:
Initial: {temperature}
After setting to {attempted_value}: {temperature}
After setting to {attempted_value}: {temperature}Wenn du beispielsweise ein Thermostat mit 20 erstellst und dann versuchst, es auf 25 (gültig) und anschließend auf 50 (ungültig) zu setzen, würde die Ausgabe wie folgt aussehen:
Initial: 20
After setting to 25: 25
After setting to 50: 25Du erhältst drei Eingaben: die Anfangstemperatur, die erste Temperatur, die versucht werden soll, und die zweite Temperatur, die versucht werden soll.
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 das Ergebnis auszugeben
// Format: "After setting to {attempted_value}: {temperature}"
// TODO: Versuche, die zweite Temperatur einzustellen und das Ergebnis auszugeben
// 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 Objektorientierte Programmierung
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Übe selbstständig: Online-Rust-Compiler