Getter und Setter
Teil des Abschnitts Object Oriented Programming der C-Journey von Coddy — Lektion 19 von 61.
Mit opaken Pointern sind die Member des Structs vor externem Code verborgen. Aber wenn externer Code nicht direkt auf die Daten zugreifen kann, wie lesen oder ändern wir sie dann? Die Antwort sind Getter- und Setter-Funktionen – öffentliche Schnittstellen, die einen kontrollierten Zugriff auf private Daten ermöglichen.
Ein Getter gibt den Wert eines verborgenen Elements zurück:
// counter.h
int counter_get_value(const Counter *c);
// counter.c
int counter_get_value(const Counter *c) {
return c->value;
}
Ein Setter modifiziert ein verborgenes Element:
// counter.h
void counter_set_value(Counter *c, int new_value);
// counter.c
void counter_set_value(Counter *c, int new_value) {
c->value = new_value;
}
Beachten Sie die Benennungskonvention: Stellen Sie Funktionen den Typnamen voran (counter_), um Konflikte zu vermeiden und die API übersichtlich zu gestalten. Getter verwenden const-Pointer, da sie das Objekt nicht verändern.
Jetzt kann externer Code sicher mit den verborgenen Daten interagieren:
// main.c
Counter *c = create_counter(10);
printf("%d\n", counter_get_value(c)); // 10
counter_set_value(c, 25);
printf("%d\n", counter_get_value(c)); // 25
Dieses Muster gibt Ihnen die vollständige Kontrolle darüber, wie auf Daten zugegriffen wird – eine Grundlage, auf der wir in der nächsten Lektion aufbauen werden, wenn wir Validierungslogik zu Settern hinzufügen.
Aufgabe
EinfachLassen Sie uns ein Score-Modul erstellen, das das Opaque-Pointer-Muster mit Getter- und Setter-Funktionen verwendet. Sie werden einen versteckten Punktezähler erstellen, bei dem externer Code nur über die von Ihnen bereitgestellte öffentliche Schnittstelle mit den Daten interagieren kann.
Sie werden drei Dateien erstellen:
score.h: Ihre öffentliche Schnittstelle. Deklarieren Sie einen opakenScore-Typ mithilfe einer Vorwärtsdeklaration (kein Struct-Body!). Deklarieren Sie diese Funktionen:create_score— nimmt eine Ganzzahl für die initialen Punkte entgegen und gibt einen Score-Pointer zurückfree_score— nimmt einen Score-Pointer entgegen und gibt den Speicher freiscore_get_points— ein Getter, der einenconst Score *entgegennimmt und die aktuellen Punkte zurückgibtscore_set_points— ein Setter, der einenScore *und eine Ganzzahl entgegennimmt und den Punktewert aktualisiert
SCORE_H.score.c: Definieren Sie das eigentlichestruct Scoremit einem einzigen versteckten Member:int points. Implementieren Sie alle vier Funktionen. Ihr Getter sollte den versteckten Wert zurückgeben und Ihr Setter sollte ihn aktualisieren. Denken Sie daran, dass Getterconst-Pointer verwenden, da sie das Objekt nicht verändern.main.c: Demonstrieren Sie Ihr Modul, indem Sie einen Score erstellen, seinen Wert lesen, ihn über den Setter ändern und ihn erneut lesen.
Sie erhalten zwei Eingaben: die initial points (eine Ganzzahl) und den new points value (eine Ganzzahl), der gesetzt werden soll.
Erstellen Sie in Ihrer Hauptdatei einen Score mit den initialen Punkten, geben Sie den aktuellen Wert mit dem Getter aus, aktualisieren Sie ihn mit dem Setter auf den neuen Wert, geben Sie den aktualisierten Wert aus, geben Sie dann den Score frei und drucken Sie eine Bestätigung.
Geben Sie die Ausgabe in diesem Format aus:
Initial: {points}
Updated: {points}
FreedZum Beispiel wäre bei den Eingaben 100 und 250 die Ausgabe:
Initial: 100
Updated: 250
FreedBeachten Sie, dass main.c nicht direkt auf points zugreifen kann — es muss über Ihre Getter- und Setter-Funktionen gehen. Dies ist Kapselung in Aktion: Sie kontrollieren genau, wie die versteckten Daten gelesen und geändert werden können.
Spickzettel
Bei opaken Pointern (opaque pointers) sind die Struct-Member vor externem Code verborgen. Um auf diese privaten Daten zuzugreifen oder sie zu ändern, verwenden Sie Getter- und Setter-Funktionen.
Ein Getter gibt den Wert eines verborgenen Members zurück und verwendet einen const-Pointer, da er das Objekt nicht verändert:
// counter.h
int counter_get_value(const Counter *c);
// counter.c
int counter_get_value(const Counter *c) {
return c->value;
}
Ein Setter modifiziert einen verborgenen Member:
// counter.h
void counter_set_value(Counter *c, int new_value);
// counter.c
void counter_set_value(Counter *c, int new_value) {
c->value = new_value;
}
Verwenden Sie eine Namenskonvention mit dem Typnamen als Präfix (counter_), um Konflikte zu vermeiden und die API zu verdeutlichen.
Externer Code interagiert über diese Funktionen mit den verborgenen Daten:
// main.c
Counter *c = create_counter(10);
printf("%d\n", counter_get_value(c)); // 10
counter_set_value(c, 25);
printf("%d\n", counter_get_value(c)); // 25
Probier es selbst
#include <stdio.h>
#include "score.h"
int main() {
int initial_points, new_points;
scanf("%d", &initial_points);
scanf("%d", &new_points);
// TODO: Erstelle ein Score mit initial_points
// TODO: Gib den Anfangswert mit dem Getter aus
// Format: "Initial: {points}"
// TODO: Aktualisiere den Punktestand mit dem Setter und new_points
// TODO: Gib den aktualisierten Wert mit dem Getter aus
// Format: "Updated: {points}"
// TODO: Gib den Speicher von score frei und gib "Freed" aus
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