Attribute, Kapselung, Setter und Getter
Das zugehoerige Arbeitsblatt ist als Mini-Projekt "Geometrische Figuren" aufgebaut. Die zentrale Aufgabe lautet dort: fehlende Setter und Getter ergaenzen und dadurch ein bereits vorbereitetes Klassenpaket vervollstaendigen. Dieses Kapitel macht aus dieser Aufgabenidee eine systematische OOP-Einheit.
Warum Kapselung unverzichtbar ist
Objekte sollen intern konsistent bleiben. Wenn Attribute beliebig von aussen veraendert werden koennen, treten schnell Fehler auf:
- negative Laengen oder Radien
- ungueltige Koordinaten
- widerspruechliche Zustandskombinationen
Darum gilt als Standardregel:
- Attribute moeglichst
private - Zugriff ueber Methoden mit klarer Bedeutung
- Pruefungen beim Setzen von Werten
Kapselung ist kein "Extra", sondern die Grundlage fuer robuste Objektmodelle.
Rolle von Attributen
Attribute speichern den Zustand eines Objekts. Im Figurenkontext sind typische Attribute:
- Position (
x,y) - Groessenwerte (
radius,breite,hoehe) - Sichtbarkeit (
sichtbar) - Farbe oder Linienstaerke
Wichtig ist die Frage: Welche dieser Daten duerfen direkt aenderbar sein, welche nur ueber kontrollierte Methoden?
Getter und Setter als Schnittstelle
Getter
Getter liefern intern gespeicherte Werte nach aussen.
public double getRadius() {
return radius;
}
Setter
Setter schreiben Werte in Attribute, aber nur mit Gueltigkeitspruefung.
public void setRadius(double radius) {
if (radius > 0) {
this.radius = radius;
}
}
Merksatz
Ein Setter ist nicht nur "Wert rein", sondern eine Fachregel: Welche Aenderungen sind erlaubt?
Beispielklasse im Figurenprojekt
public class Kreis {
private int x;
private int y;
private double radius;
private boolean sichtbar;
public Kreis(int x, int y, double radius) {
this.x = x;
this.y = y;
setRadius(radius);
sichtbar = true;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public double getRadius() {
return radius;
}
public boolean isSichtbar() {
return sichtbar;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setRadius(double radius) {
if (radius > 0) {
this.radius = radius;
}
}
public void setSichtbar(boolean sichtbar) {
this.sichtbar = sichtbar;
}
}
Dieses Muster passt direkt zur Blattaufgabe "fehlende Setter und Getter ergaenzen".
Was im Mini-Projekt typischerweise fehlt
Beim Vervollstaendigen eines halbfertigen Projekts fehlen oft genau diese Punkte:
- Getter fuer einzelne Attribute
- Setter mit Gueltigkeitspruefung
- einheitliche Namenskonvention (
get...,set...,is...) - saubere Verwendung von
thisbei Namensgleichheit
Beispiel:
public void setX(int x) {
this.x = x;
}
Ohne this wuerde der Parameter x sich selbst zugewiesen werden.
Setter brauchen Fachregeln, nicht nur Syntax
Ein guter Setter prueft, ob die Aenderung fachlich erlaubt ist.
Kreisradius
- erlaubt:
radius > 0 - nicht erlaubt:
radius <= 0
Rechteckgroesse
- erlaubt:
breite > 0 && hoehe > 0 - optional: Obergrenzen, falls Zeichenflaeche begrenzt ist
Sichtbarkeit
- oft nur direktes Setzen von
true/false - alternativ domaenennahe Methoden:
anzeigen(),verbergen()
Damit wird der Code sprechender als mit einem generischen Setter.
Wann ein Attribut keinen Setter haben sollte
Nicht jedes Attribut sollte aenderbar sein.
Beispiele:
- Erzeugungszeitpunkt
- eindeutige ID
- intern berechneter Cache
In solchen Faellen:
- Getter ja
- Setter nein
Das reduziert unbeabsichtigte Seiteneffekte.
Zusammenspiel mit Konstruktoren
Im Arbeitsblattkontext ist es sinnvoll, Konstruktoren und Setter zu verbinden:
- Konstruktor setzt Anfangszustand
- Setter erzwingen dieselben Regeln auch spaeter
Muster:
public Rechteck(int breite, int hoehe) {
setBreite(breite);
setHoehe(hoehe);
}
So steht die Validierung nur an einer Stelle und wird nicht dupliziert.
Teststrategie fuer das Blattprojekt
Fuer jede ergaenzte Klasse sollten mindestens diese Tests laufen:
- gueltige Werte setzen
- ungueltige Werte setzen
- Ruecklesen per Getter
- Kombination mehrerer Aenderungen
- Randfaelle (0, negative Werte, sehr grosse Werte)
Beispieltestidee:
setRadius(10)->getRadius()ist10setRadius(-3)-> Wert bleibt unveraendert
Typische Fehler im Kapitel
- Attribute
publiclassen Dann kann niemand Regeln erzwingen. - Setter ohne Pruefung Objekte werden inkonsistent.
thisvergessen Namenskonflikte fuehren zu wirkungslosen Settern.- Automatisch fuer alles Setter erzeugen Das oeffnet mehr Schnittstellen als noetig.
- Berechnete Werte speichern statt ableiten
Besser oft: bei Bedarf berechnen (
getFlaeche()).
Erweiterte Aufgaben zur Vertiefung
- Ergaenze in allen Figurenklassen fehlende Getter und Setter.
- Fuehre fuer alle Groessenattribute die Regel "nur > 0" ein.
- Ersetze
setSichtbar(boolean)durchanzeigen()undverbergen(). - Implementiere
verschiebe(int dx, int dy)ueberxundy. - Schreibe eine kurze Dokumentation, welche Attribute absichtlich keinen Setter bekommen.
Verbindung zu den naechsten Kapiteln
Dieses Kapitel bereitet direkt vor auf:
- Konstruktoren und Ueberladen
- Sichtbarkeit (
private/protected/public) - Vererbung in Figurenhierarchien
Wer Kapselung sauber umsetzt, hat spaeter deutlich weniger Probleme mit Vererbungsdesign und Nebenwirkungen.
Fazit
Die Aussage des Arbeitsblatts bleibt der Kern:
- Fehlende Setter und Getter nachtragen ist nicht nur Fleissarbeit.
- Es ist der Schritt von "Code existiert" zu "Klassen sind robust modelliert".
- Gute Kapselung sorgt dafuer, dass Objekte nur gueltige Zustaende annehmen.
Mini-Projekt: Geometrische Figuren
Die Kapitelvorlage nutzt ein Figurenprojekt mit Klassen wie Kreis und Quadrat.
Ziel ist, fehlende Setter/Getter zu ergaenzen und dabei konsistente Zustaende zu sichern.
Invarianten explizit dokumentieren
Zu jeder Klasse im Figurenprojekt sollte eine kurze Invariantenliste gehoeren. Beispiel Kreis:
radius > 0xundysind ganzzahlige Koordinaten- Sichtbarkeit ist stets definiert (
trueoderfalse)
Diese Liste ist mehr als Doku. Sie bestimmt direkt, welche Pruefungen in Konstruktoren und Settern noetig sind.
Konstruktor und Setter konsistent halten
Ein haeufiger Fehler: Konstruktor prueft Werte, Setter aber nicht (oder umgekehrt). Das fuehrt zu inkonsistentem Verhalten.
Regel:
- Alle Wege, die den Zustand aendern, muessen dieselben Regeln durchsetzen.
Muster:
public Kreis(int x, int y, double radius) {
this.x = x;
this.y = y;
setRadius(radius);
}
So wird die Validierungslogik nur an einer Stelle gepflegt.
Getter als Fachschnittstelle statt Rohdatenexport
Getter muessen nicht immer nur Feldwerte durchreichen. Sie koennen auch fachliche Ableitungen liefern.
Beispiel:
public double getFlaeche() {
return Math.PI * radius * radius;
}
Vorteile:
- keine redundante Speicherung abgeleiteter Werte
- immer konsistente Berechnung auf Basis des aktuellen Zustands
Wann Setzen verweigert werden sollte
Das Blatt fordert das Ergaenzen fehlender Setter. Bei Vertiefung ist wichtig: Manche Setzversuche sollen bewusst scheitern.
Moegliche Strategien:
- still ignorieren
booleanfuer Erfolg/Fehlschlag zurueckgebenIllegalArgumentExceptionwerfen
Fuer den Unterricht ist boolean oft gut nachvollziehbar, fuer groessere Systeme sind Exceptions oft klarer.
Kapselung und Testbarkeit
Kapselung verbessert nicht nur Sicherheit, sondern auch Tests:
- durch Getter kann Zustand gezielt geprueft werden
- durch validierende Setter lassen sich Fehlfaelle reproduzierbar testen
Testbeispiel:
setRadius(5)-> ErfolgsetRadius(-2)-> MisserfolggetRadius()bleibt5
Das ist ein klarer Nachweis, dass die Klasse Invarianten schuetzt.
Vermeidung von "anemischen" Klassen
Ein Risiko bei vielen Settern/Gettern: Klassen werden zu reinen Datensaecken ohne Verhalten.
Gegenmassnahme:
- wichtige Fachaktionen als Methoden modellieren
- nicht nur
setX, sondern z. B.verschiebe(dx, dy) - nicht nur
setSichtbar, sondernanzeigen()undverbergen()
So bleibt das Objektmodell fachlich ausdrucksstark.
Beispiel: Rechteck mit konsistenten Regeln
public class Rechteck {
private double breite;
private double hoehe;
public Rechteck(double breite, double hoehe) {
setBreite(breite);
setHoehe(hoehe);
}
public double getBreite() {
return breite;
}
public double getHoehe() {
return hoehe;
}
public boolean setBreite(double breite) {
if (breite <= 0) return false;
this.breite = breite;
return true;
}
public boolean setHoehe(double hoehe) {
if (hoehe <= 0) return false;
this.hoehe = hoehe;
return true;
}
public double getFlaeche() {
return breite * hoehe;
}
}
Dieses Muster zeigt die Kombination aus Kapselung, Validierung und fachlicher Methode.
Namenskonventionen im Kapitel
getXfuer WerteisSichtbarfuer booleanssetXfuer gezielte Aenderungen- fachliche Verben fuer Aktionen (
verschiebe,skaliere,zeichne)
Konsequente Namensgebung erhoeht Lesbarkeit und erleichtert Teamarbeit.
Uebungspaket zur Vertiefung
- Ergaenze in allen Figurenklassen Invarianten als Kommentarblock.
- Vereinheitliche alle Setter auf dieselbe Fehlerstrategie.
- Fuege zu jeder Klasse mindestens eine fachliche Methode ohne Setter-Charakter hinzu.
- Implementiere
kopiere()oder Copy-Konstruktor fuer eine Figur. - Schreibe fuer jede Klasse drei Tests:
- gueltiger Zustand
- ungueltiger Zustand
- Zustand nach mehreren Aenderungen
Debug-Checkliste fuer Zustandsfehler
- Welcher Setter/Konstruktor hat den Zustand zuletzt geaendert?
- Wurde
thiskorrekt verwendet? - Wird ein ungueltiger Wert still akzeptiert?
- Sind alle Felder nach Konstruktion initialisiert?
- Gibt es abgeleitete Werte, die veralten koennen?
Diese Fragen loesen einen grossen Teil typischer OOP-I-Probleme.
Bewertungsdimensionen fuer das Mini-Projekt
- Korrekte Sichtbarkeit (
privatestatt offener Felder) - Vollstaendige Getter/Setter gemaess Aufgabenstellung
- Gueltigkeitspruefungen bei kritischen Attributen
- Konsistente Namensgebung
- Nachvollziehbare Tests
Zusammenfassung der Vertiefung
Die Arbeitsblattaufgabe "fehlende Setter/Getter ergaenzen" wird erst dann wirklich stark, wenn sie mit Invarianten, Fehlerstrategie und Testdisziplin verbunden wird. Genau dadurch wird aus einem formalen OOP-Schritt ein belastbares Klassendesign.
Abschlussprojekt zur Kapselung
Baue eine Klasse Schuelerprofil mit Attributen fuer Name, Klasse, Notendurchschnitt und Aktivstatus.
Regeln:
- Name darf nicht leer sein.
- Notendurchschnitt muss zwischen 1.0 und 6.0 liegen.
- Aktivstatus wird nur ueber fachliche Methoden geaendert (
aktivieren,deaktivieren).
Aufgabe:
- implementiere sinnvolle Getter
- setze nur dort Setter ein, wo fachlich noetig
- begruende kurz, welche Felder bewusst keinen Setter erhalten
Diese Aufgabe prueft, ob Kapselung als Designprinzip verstanden wurde und nicht nur als Syntaxmuster.
Pruefungsnahe Kurzfragen
- Was ist eine Invariante, und wo wird sie im Code abgesichert?
- Warum ist
thisin manchen Settern notwendig? - Wann ist ein Getter sinnvoll, wann nicht?
- Nenne ein Attribut, das bewusst keinen Setter haben sollte, und begruende dies.
Diese Fragen pruefen, ob Kapselung als Entwurfsprinzip verstanden wurde.
Kurze Transferfrage
Nenne ein Attribut aus einem eigenen Projekt, das bisher direkt gesetzt wird, und formuliere eine fachliche Methode, die dieses Setzen kapselt (z. B. erhoehePunktestand, setzeStatusAktiv). Begruende kurz, welche Fehler dadurch verhindert werden.
