MINT lernen

Übungen: Datenkapselung mit get und set

Ein privates Attribut ist wie ein Tresor mit Schalter: Wer etwas will, muss an der Methode vorbei — und die darf Nein sagen.

Dein Fortschritt:
0 / 0 Aufgaben
1

Übungsaufgaben

Zehn Übungen zum Klicken, Ziehen und Knobeln — von AFB I bis AFB III. Jede Übung gibt dir sofort Rückmeldung; wenn du hängst, helfen dir die gestuften Tipps.

A1
Warum private?
AFB I

Die Software einer Tierarztpraxis nutzt diese Klasse. Welche Aussagen zur Datenkapselung stimmen?

Tier
  • - name: Zeichenkette
  • - gewichtKg: Fließkommazahl
  • c Tier(name: Zeichenkette, gewichtKg: Fließkommazahl)
  • + getName(): Zeichenkette
  • + getGewichtKg(): Fließkommazahl
  • + setGewichtKg(gewichtKg: Fließkommazahl)
Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Prüfen“.
private verbietet nur den direkten Zugriff von außen — über öffentliche Methoden wie den Getter darf der Wert sehr wohl nach außen. Getter und Setter sind unabhängig: Lässt man den Setter weg, ist das Attribut nur lesbar (hier: der Name). Mit Speicher oder Geschwindigkeit hat Kapselung nichts zu tun; es geht darum, dass das Objekt immer einen gültigen Zustand hat.
Ansatz: Unterscheide: direkter Zugriff auf das Attribut vs. Zugriff über eine öffentliche Methode.
Weiter: Was passiert, wenn es einen Getter, aber keinen Setter gibt? Und wo könnte man eine Prüfung wie „Gewicht > 0“ unterbringen?
A2
Stimmt's? — Die Liefer-Drohne
AFB I

Eine Liefer-Drohne hat das private Attribut akku (0 bis 100 %) und das private Attribut gesperrt (Wahrheitswert). Fünf Behauptungen zu Gettern und Settern:

Fünf Aussagen nacheinander. Eine falsche Einschätzung reicht — dann startest du die Serie mit „Neue Runde“ neu.
Aussage 1 von 5

Merksatz: Getter liefern (Rückgabetyp, kein Parameter), Setter setzen (void, ein Parameter, mit Prüfung). private gilt ohne Ausnahme — auch für „harmlose“ Werte.
Ansatz: Stell dir die Köpfe von getAkku und setAkku vor: Was geht hinein, was kommt heraus?
Weiter: Der Compiler prüft Sichtbarkeit, nicht den Wert. Ob 50 gültig wäre, spielt für private keine Rolle.
A3
Was darf eine andere Klasse?
AFB I

Die Klasse Hotelzimmer ist wie im Diagramm implementiert. In einer anderen Klasse gibt es ein Objekt z. Welche Zeilen lassen sich übersetzen?

Hotelzimmer
  • - nummer: Ganzzahl
  • - preis: Ganzzahl
  • - belegt: Wahrheitswert
  • c Hotelzimmer(nummer: Ganzzahl)
  • + getPreis(): Ganzzahl
  • + setPreis(preis: Ganzzahl)
  • + istBelegt(): Wahrheitswert
Ziehe jede Karte in den passenden Korb — oder wähle sie mit Enter aus und drücke dann die Ziffer des Korbs (0 legt sie zurück).
1wird übersetzt
2Übersetzungsfehler
Von außen gibt es nur den Weg über die öffentlichen Methoden: Direkte Zugriffe auf preis oder belegt scheitern an private. z.getPreis() = 90; ist ein häufiger Denkfehler — einem Rückgabewert kann man nichts zuweisen. Und setPreis() ohne Wert passt nicht zur Parameterliste. Die Zeile mit setPreis(z.getPreis() + 10) ist dagegen der saubere Weg, einen Preis zu erhöhen.
Ansatz: Frage bei jeder Zeile: Wird ein privates Attribut direkt angefasst — oder eine öffentliche Methode passend aufgerufen?
Weiter: Prüfe bei Methodenaufrufen auch die Parameter: Stimmt die Anzahl mit der Klassenkarte überein? Und steht die Methode links vom Gleichheitszeichen?
A4
Ein Setter mit Prüfung
AFB II

Eine Pflanze im Gewächshaus soll alle 1 bis 14 Tage gegossen werden. Ergänze den Setter für das Attribut intervall — ein Baustein bleibt übrig.

Wort anklicken, dann Lücke anklicken (oder umgekehrt) — mit Tab und Enter geht es genauso. Ein Klick auf eine gefüllte Lücke legt das Wort zurück.

public setIntervall( intervall) {
     (intervall >= 1 intervall <= 14) {
        .intervall = intervall;
    }
}

|| bleibt übrig — und ist der Klassiker unter den Setter-Fehlern: intervall >= 1 || intervall <= 14 ist für jede Zahl wahr (−5 ist kleiner als 14, 99 ist größer als 1), die Prüfung wäre wirkungslos. Ohne this würde sich der Parameter nur selbst zugewiesen, das Attribut bliebe unverändert.
Ansatz: Ein Setter liefert nichts zurück und bekommt den neuen Wert als ganze Zahl.
Weiter: Beide Bedingungen müssen gleichzeitig gelten. Und weil Parameter und Attribut gleich heißen, braucht die Zuweisung ein Schlüsselwort.
A5
Plausibilitätsprüfungen der Wetterstation
AFB IIMix

Die Klasse Messwert einer Wetterstation prüft in ihren Settern jeden neuen Wert x. Verbinde jede Regel mit der passenden Bedingung — denk an die logischen Operatoren aus Kapitel 1.

Ansatz: Prüfe jede Bedingung mit den Randwerten: Ist 0 erlaubt? Ist 24 (bzw. 360) erlaubt?
Weiter: Die verneinte Bedingung beschreibt, was nicht ungültig ist. Welche Werte bleiben übrig, wenn man alles unter 1 und über 12 ausschließt?
A6
Lautsprecher der Playlist-App
AFB II

Die Playlist-App steuert einen Lautsprecher (Lautstärke 0 bis 100).

public class Lautsprecher {
    private int lautstaerke;

    public Lautsprecher() {
        lautstaerke = 30;
    }

    public void setLautstaerke(int lautstaerke) {
        if (lautstaerke >= 0 && lautstaerke <= 100) {
            this.lautstaerke = lautstaerke;
        }
    }

    public void lauter() {
        setLautstaerke(lautstaerke + 15);
    }

    public int getLautstaerke() {
        return lautstaerke;
    }
}
Lautsprecher box = new Lautsprecher();
box.setLautstaerke(120);
box.lauter();
box.setLautstaerke(-5);
box.lauter();
box.lauter();
box.lauter();
box.lauter();

Welchen Wert liefert danach box.getLautstaerke()?

Rechne selbst und trage das Ergebnis ein — Enter prüft direkt.
Verlauf: 30 → (120 abgelehnt) 30 → 45 → (−5 abgelehnt) 45 → 60 → 75 → 90 → 105 wäre zu laut, also abgelehnt: 90. Häufiger Fehler: 100, weil man annimmt, der Setter „deckelt“ auf den Höchstwert — er lehnt ungültige Werte aber komplett ab. Beachte: Weil lauter() den Setter benutzt, gilt die Prüfung auch intern.
Ansatz: Schreibe nach jeder Zeile den aktuellen Wert von lautstaerke auf.
Weiter: Der Setter übernimmt nur Werte von 0 bis 100 — sonst bleibt der alte Wert stehen. lauter() geht ebenfalls durch den Setter.
A7
Konstruktor und Setter: Was passiert wann?
AFB II

Für eine Klassenfahrt werden Teilnehmer erfasst; erlaubt ist ein Alter von 10 bis 20 Jahren. Der Konstruktor nutzt den Setter mit.

public class Teilnehmer {
    private String name;
    private int alter;

    public Teilnehmer(String name, int alter) {
        this.name = name;
        setAlter(alter);
    }

    public void setAlter(int alter) {
        if (alter >= 10 && alter <= 20) {
            this.alter = alter;
        }
    }

    public int getAlter() {
        return alter;
    }
}
Teilnehmer t = new Teilnehmer("Jona", 71);
t.setAlter(17);
int a = t.getAlter();

Bring die Ereignisse in die Reihenfolge, in der sie ablaufen.

Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1Der Konstruktor weist dem Attribut name den Wert "Jona" zu.
2Der Konstruktor ruft setAlter(71) auf.
3Die Prüfung liefert false — alter behält seinen Startwert 0.
4Von außen wird t.setAlter(17) aufgerufen; die Prüfung liefert true.
5Das Attribut alter erhält den Wert 17.
6getAlter() liefert 17 zurück.
Oft wird angenommen, der Konstruktor setze 71 einfach, weil er „von innen“ arbeitet. Hier ruft er aber den Setter auf — deshalb gilt die Prüfung auch beim Erzeugen, und der Tippfehler 71 landet nie im Objekt. Ein nicht gesetztes int-Attribut hat in Java den Startwert 0. Genau das ist der Vorteil, wenn Konstruktoren Setter nutzen: Kein Objekt startet mit einem ungültigen Zustand.
Ansatz: Was passiert zuerst: der Konstruktor oder der Aufruf t.setAlter(17)?
Weiter: Innerhalb des Konstruktors laufen die Zeilen von oben nach unten; der Setter-Aufruf springt in setAlter und prüft 71 gegen 10 bis 20.
A8
Der Kaffeeautomat im Lehrerzimmer
AFB III

Der Wassertank fasst 0 bis 2000 ml; tassen zählt die gekochten Tassen und ist nur lesbar.

public class Kaffeeautomat {
    private int wasser;
    private int tassen;

    public Kaffeeautomat() {
        wasser = 1000;
        tassen = 0;
    }

    public void setWasser(int ml) {
        if (ml >= 0 && ml <= 2000) {
            wasser = ml;
        }
    }

    public void nachfuellen(int ml) {
        setWasser(wasser + ml);
    }

    public boolean kaffeeKochen() {
        if (wasser >= 150) {
            wasser = wasser - 150;
            tassen = tassen + 1;
            return true;
        }
        return false;
    }

    public int getWasser() {
        return wasser;
    }

    public int getTassen() {
        return tassen;
    }
}
Kaffeeautomat k = new Kaffeeautomat();
k.nachfuellen(1200);
k.kaffeeKochen();  // viermal hintereinander
k.kaffeeKochen();
k.kaffeeKochen();
k.kaffeeKochen();
k.setWasser(-100);
k.kaffeeKochen();  // dreimal hintereinander
k.kaffeeKochen();
k.kaffeeKochen();
k.nachfuellen(1900);
Rechne die Kette Schritt für Schritt: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
  1. Wert von k.getWasser() direkt nach nachfuellen(1200) ml
  2. Wert von k.getTassen() nach allen kaffeeKochen-Aufrufen Tassen
  3. Wert von k.getWasser() ganz am Ende ml
  4. Transfer: Wie viele Tassen lassen sich mit dem Endstand noch höchstens kochen? Tassen
Die Falle steckt im ersten Schritt: 1000 + 1200 = 2200 ist ungültig, also lehnt der Setter ab — der Tank bleibt bei 1000, er wird nicht auf 2000 aufgefüllt. Dann 4 Tassen (1000 → 400), setWasser(−100) wird abgelehnt, 2 weitere Tassen (400 → 250 → 100), die siebte scheitert. Am Ende 100 + 1900 = 2000, das ist erlaubt. 2000 / 150 = 13 Rest 50. tassen hat keinen Setter — nur kaffeeKochen() kann den Zähler erhöhen.
Ansatz: Prüfe bei jedem nachfuellen, ob die Summe im erlaubten Bereich liegt. Nur dann ändert sich wasser.
Weiter: Jede erfolgreiche Tasse braucht mindestens 150 ml. Bei 100 ml liefert kaffeeKochen() false und ändert nichts.
A9
Fehlersuche: Medium der Stadtbücherei
AFB III

Anforderungen: Der Titel eines Mediums darf nach dem Erzeugen nur noch gelesen werden; die Ausleihfrist ist von außen lesbar und darf nur Werte von 1 bis 28 Tagen annehmen. Drei Zeilen erfüllen die Anforderungen nicht oder lassen sich nicht übersetzen.

In diesem Text stecken Fehler. Klicke genau die falschen Zeilen an — die richtigen musst du stehen lassen.
Der Setter für den Titel ist kein Syntaxfehler — er verletzt die Anforderung „nur lesbar“. Das ist der Fehler, den man in Klausuren am leichtesten übersieht: Kapselung heißt nicht „zu jedem Attribut Getter und Setter“, sondern bewusst entscheiden, was von außen erlaubt ist. Die ||-Prüfung ist der zweite Klassiker: Sie sieht nach Kontrolle aus, lässt aber alles durch.
Ansatz: Vergleiche jede Methode mit den Anforderungen: Welche Zugriffe sollen erlaubt sein, welche nicht?
Weiter: Prüfe außerdem Rückgabetyp und return auf Verträglichkeit — und teste die Bedingung im Setter gedanklich mit 50.
A10
Trickaufgabe: Der Aufzug im Schulgebäude
AFB IIITrick

Ein Aufzug fährt zwischen Erdgeschoss (0) und vierter Etage (4). Jede Zeile startet mit einem neuen Aufzug Aufzug a = new Aufzug();. In welcher Etage steht er danach?

public class Aufzug {
    private int etage;

    public Aufzug() {
        etage = 0;
    }

    public void setEtage(int etage) {
        if (etage >= 0 && etage <= 4) {
            this.etage = etage;
        }
    }

    public void hoch() {
        etage = etage + 1;
    }

    public void runter() {
        setEtage(etage - 1);
    }

    public int getEtage() {
        return etage;
    }
}
Wähle für jede Zeile eine Stufe: 0 = Etage 0, 1 = Etage 1, 2 = Etage 2, 3 = Etage 3, 4 = Etage 4. Mit der Tastatur: Tab zur Zeile, ←/→ zwischen den Stufen, Enter setzt.
0 = Erdgeschoss4 = vierte Etage
a.setEtage(3); a.hoch();
a.setEtage(5); a.hoch();
a.runter(); a.runter();
a.setEtage(4); a.hoch(); a.runter(); a.runter();
a.hoch(); a.hoch(); a.setEtage(7); a.runter();
Der Trick: hoch() umgeht den Setter und prüft nichts. In Zeile 4 steht der Aufzug deshalb kurz in der (nicht existierenden) Etage 5; das erste runter() führt nach 4, das zweite nach 3. Wer glaubt, hoch() werde bei 4 gestoppt, kommt auf 2. Moral: Eine Prüfung im Setter schützt nur, wenn alle Änderungen durch den Setter laufen — hoch() sollte setEtage(etage + 1) aufrufen.
Ansatz: Vergleiche hoch() und runter(): Welche der beiden Methoden nutzt die Prüfung im Setter?
Weiter: Ungültige setEtage-Aufrufe ändern nichts. hoch() erhöht dagegen immer — auch über 4 hinaus.