Validierung in Settern
Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 20 von 61.
In der vorherigen Lektion haben wir grundlegende Setter erstellt, die einfach Werte zuweisen. Aber dabei geht ein entscheidender Vorteil der Kapselung verloren: die Fähigkeit, Ihre Daten zu schützen, indem Validierungslogik hinzugefügt wird.
Betrachten Sie einen Counter, der niemals negativ werden sollte. Ohne Kapselung könnte jeder c->value = -50 schreiben und den Zustand korrumpieren. Mit einem Setter kontrollieren Sie, welche Werte zulässig sind:
// counter.c
void counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return; // Ungültige Eingabe stillschweigend ablehnen
}
c->value = new_value;
}Jetzt werden negative Werte einfach ignoriert.
Sie können sich auch dafür entscheiden, einen Statuscode zurückzugeben, um Erfolg oder Misserfolg anzuzeigen:
int counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return 0; // Fehlgeschlagen
}
c->value = new_value;
return 1; // Erfolgreich
}Dieses Muster lässt den Aufrufer wissen, ob die Operation erfolgreich war. Die entscheidende Erkenntnis ist, dass es bei Settern nicht nur um die Zuweisung geht – sie sind Gatekeeper, die Regeln darüber durchsetzen, wie der Zustand Ihres Objekts aussehen darf. Dies ist die wahre Stärke der Kapselung: Ihr Objekt bewahrt seine eigene Integrität, unabhängig davon, was externer Code zu tun versucht.
Aufgabe
EinfachLassen Sie uns ein Temperature-Modul erstellen, das seine Daten mithilfe von Validierung im Setter schützt. Sie werden einen Temperatur-Tracker erstellen, der nur Werte innerhalb eines gültigen Bereichs akzeptiert – dies demonstriert, wie Setter als Gatekeeper für den Zustand Ihres Objekts fungieren.
Sie werden drei Dateien erstellen:
temperature.h: Ihre öffentliche Schnittstelle unter Verwendung des Opaque-Pointer-Musters. Deklarieren Sie einenTemperature-Typ nur mit einer Vorwärtsdeklaration. Deklarieren Sie diese Funktionen:create_temperature— nimmt eine Ganzzahl für die Anfangsgrade entgegen und gibt einen Temperature-Pointer zurückfree_temperature— gibt den zugewiesenen Speicher freitemp_get_degrees— Getter, der den aktuellen Temperaturwert zurückgibttemp_set_degrees— Setter, der einenintzurückgibt (1 für Erfolg, 0 für Misserfolg)
TEMPERATURE_H.temperature.c: Definieren Sie das eigentlichestruct Temperaturemit einem verborgenenint degrees-Member. Implementieren Sie alle Funktionen. Der Schlüssel liegt in Ihrem Setter – er sollte nur Werte zwischen -50 und 150 (einschließlich) akzeptieren. Wenn der Wert außerhalb dieses Bereichs liegt, geben Sie 0 zurück und lassen Sie die Temperatur unverändert. Wenn er gültig ist, aktualisieren Sie den Wert und geben Sie 1 zurück.main.c: Demonstrieren Sie die Validierung, indem Sie versuchen, sowohl gültige als auch ungültige Temperaturen zu setzen, und zeigen Sie, dass ungültige Werte abgelehnt werden, während gültige akzeptiert werden.
Sie erhalten drei Eingaben: die Anfangstemperatur, eine zu setzende gültige Temperatur (innerhalb des Bereichs) und eine zu versuchende ungültige Temperatur (außerhalb des Bereichs).
Erstellen Sie in Ihrer Hauptdatei eine Temperature mit dem Anfangswert und geben Sie diese aus. Versuchen Sie dann, die ungültige Temperatur zu setzen – da diese abgelehnt werden sollte, geben Sie das Ergebnis aus und zeigen Sie, dass der Wert unverändert bleibt. Setzen Sie schließlich die gültige Temperatur, geben Sie das Erfolgsergebnis aus und zeigen Sie den aktualisierten Wert. Geben Sie den Speicher frei und bestätigen Sie die Bereinigung.
Geben Sie die Ausgabe in diesem Format aus:
Initial: {degrees}
Set {invalid}: {0 or 1}
After invalid: {degrees}
Set {valid}: {0 or 1}
After valid: {degrees}
FreedZum Beispiel wäre bei den Eingaben 25, 100 und 200 die Ausgabe:
Initial: 25
Set 200: 0
After invalid: 25
Set 100: 1
After valid: 100
FreedDies demonstriert die wahre Stärke der Kapselung – Ihr Setter erzwingt die Regeln darüber, was eine gültige Temperatur ausmacht, und schützt die Integrität des Objekts, unabhängig davon, welche Werte externer Code zuzuweisen versucht.
Spickzettel
Setter können Validierungslogik enthalten, um die Datenintegrität zu schützen. Anstatt Werte einfach nur zuzuweisen, fungieren sie als Gatekeeper, die Regeln für gültige Objektzustände erzwingen.
Einfaches Validierungsbeispiel – stillschweigendes Ablehnen ungültiger Eingaben:
void counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return; // Ungültige Eingabe ablehnen
}
c->value = new_value;
}Rückgabe eines Statuscodes, um Erfolg oder Misserfolg anzuzeigen:
int counter_set_value(Counter *c, int new_value) {
if (new_value < 0) {
return 0; // Fehler
}
c->value = new_value;
return 1; // Erfolg
}Dieses Muster ermöglicht es Aufrufern zu prüfen, ob die Operation erfolgreich war, sodass Objekte ihre eigene Integrität unabhängig von externen Codeversuchen bewahren können.
Probier es selbst
#include <stdio.h>
#include "temperature.h"
int main() {
// Eingaben lesen
int initial, valid_temp, invalid_temp;
scanf("%d", &initial);
scanf("%d", &valid_temp);
scanf("%d", &invalid_temp);
// TODO: Erstelle eine Temperature mit dem Initialwert
// TODO: Initialtemperatur ausgeben
// Format: "Initial: {degrees}"
// TODO: Versuche, die ungültige Temperatur zu setzen
// Das Ergebnis ausgeben und zeigen, dass der Wert unverändert bleibt
// Format: "Set {invalid}: {0 or 1}"
// Format: "After invalid: {degrees}"
// TODO: Die gültige Temperatur setzen
// Das Erfolgsresultat ausgeben und den aktualisierten Wert zeigen
// Format: "Set {valid}: {0 or 1}"
// Format: "After valid: {degrees}"
// TODO: Speicher freigeben und "Freed" ausgeben
return 0;
}
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
1Grundlagen der modularen Programmierung
Header-DateienInclude GuardsQuelldateienStatische FunktionenWiederholung: Modularer Taschenrechner4Kapselung
Konzept der Opaque PointersOpaque Structs definierenGetter und SetterValidierung in SetternRückblick: Die geheime Box2Objekte und Methoden
Structs als ObjekteDer 'Self'-PointerConst-CorrectnessPointer vs. WertHilfsmethodenZusammenfassung: Point Manager5Projekt: Einfaches Bankkonto
Projekt-SetupImplementierung des Kontos3Objekt-Lebenszyklus
Konstruktor-MusterDestruktor-MusterStack-InitialisierungTiefe KopieRückblick: String-Wrapper6Vererbung durch Komposition
Struct-EinbettungDie First-Member-RegelZugriff auf Parent-MemberUpcastingRückblick: Formenhierarchie9Projekt: Formen-Zeichner
ProjektübersichtKreis-Implementierung