MINT lernen

Vererbung

Wie viel Code sparst du dir, wenn eine Klasse einfach alles von einer anderen übernimmt — und was, wenn sie es besser weiß?

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
Ist das ein „ist ein“?
AFB I

Vererbung passt nur, wenn jedes Objekt der Unterklasse auch ein Objekt der Oberklasse ist. Welche Klassenköpfe sind sinnvoll modelliert?

Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Prüfen“.
Test: Satz „Jede Gitarre ist ein Instrument“ — stimmt, also passt extends. „Eine Saite ist eine Gitarre“ stimmt nicht: Die Gitarre hat Saiten, eine Schule hat Klassenräume — das sind Beziehungen, keine Vererbung. Instrument extends Gitarre hat die Richtung vertauscht: Das Allgemeinere ist die Oberklasse.
Ansatz: Lies jede Zeile als Satz: „Jede <Unterklasse> ist ein(e) <Oberklasse>.“
Weiter: „hat ein“ ist keine Vererbung. Und hinter extends steht immer das Allgemeinere.
A2
Stimmt's? — Die Nachrichten-App
AFB I

In einer Messenger-App gilt class Sprachnachricht extends Nachricht. Die Oberklasse hat das private Attribut absender und den öffentlichen Getter getAbsender().

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

Geerbt wird alles — aber private bleibt privat, auch vor der eigenen Unterklasse. Das Objekt hat also ein Attribut absender, der Code in Sprachnachricht darf es nur nicht direkt anfassen.
Ansatz: Unterscheide: Was hat das Objekt (alles Geerbte) — und was darf der Code der Unterklasse direkt benutzen?
Weiter: @Override ist eine Annotation — ein Hinweis an den Compiler, kein Muss.
A3
Geerbt, neu oder überschrieben?
AFB I

Was hat ein Sprachnachricht-Objekt — und woher kommt es?

public class Nachricht {
    private String absender;

    public Nachricht(String absender) {
        this.absender = absender;
    }

    public String getAbsender() {
        return absender;
    }

    public String vorschau() {
        return "Neue Nachricht";
    }

    public int groesseKB() {
        return 1;
    }
}
public class Sprachnachricht extends Nachricht {
    private int sekunden;

    public Sprachnachricht(String absender, int sekunden) {
        super(absender);
        this.sekunden = sekunden;
    }

    @Override
    public String vorschau() {
        return "Sprachnachricht (" + sekunden + " s)";
    }

    @Override
    public int groesseKB() {
        return sekunden * 16;
    }

    public int getSekunden() {
        return sekunden;
    }
}
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).
1geerbt
2neu in der Unterklasse
3überschrieben
Überschrieben ist eine Methode, die in beiden Klassen mit gleicher Signatur steht — dann läuft die Version der Unterklasse: Eine 12-Sekunden-Nachricht meldet groesseKB() = 192. Auch das private Attribut absender ist geerbt: Es steckt im Objekt und wird über super(absender) gesetzt. (Mit java geprüft.)
Ansatz: Steht es nur in Nachricht, nur in Sprachnachricht — oder in beiden?
Weiter: @Override markiert die überschriebenen Methoden.
A4
Ein Sparkonto erbt vom Konto
AFB II

Die Klasse Konto hat den Konstruktor Konto(String inhaber) und die Methode beschreibung(), die z. B. "Ida: 0.0 Euro" liefert. Ergänze die Unterklasse — zwei Bausteine bleiben ü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 class Sparkonto Konto {
    private double zinssatz;
    public Sparkonto(String inhaber, double zinssatz) {
        (inhaber);
        this.zinssatz = zinssatz;
    }
    
    public String beschreibung() {
        return super.() + ", Zinsen: " + zinssatz + " %";
    }
}

super(inhaber) ruft den Konstruktor von Konto auf — Konto(inhaber) allein wäre für javac eine unbekannte Methode. super.beschreibung() holt den Text der Oberklasse und ergänzt ihn: new Sparkonto("Ida", 1.5).beschreibung() liefert Ida: 0.0 Euro, Zinsen: 1.5 %. (Mit java geprüft.)
Ansatz: Welches Schlüsselwort steht im Klassenkopf für „erbt von“? Und wie ruft man den Konstruktor der Oberklasse auf?
Weiter: Über der überschreibenden Methode steht die Annotation; super. ruft die gleichnamige Methode der Oberklasse.
A5
Was passiert bei new Sparkonto(…)?
AFB II

Bring die Vorgänge bei Sparkonto s = new Sparkonto("Ida", 1.5); in die richtige Reihenfolge (Klassen wie in A4; Konto hat außerdem das Attribut kontostand).

Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1Der Konstruktor von Sparkonto startet mit "Ida" und 1.5.
2super("Ida") ruft den Konstruktor von Konto auf.
3Konto setzt inhaber auf "Ida"; kontostand bleibt 0.0.
4Zurück im Konstruktor von Sparkonto: zinssatz wird 1.5.
5s verweist auf das fertige Objekt — mit inhaber, kontostand und zinssatz.
Ein Unterklassen-Objekt ist ein Objekt mit allen Attributen beider Klassen — es entstehen nicht zwei Objekte. Der Oberklassen-Teil wird zuerst fertig gebaut; deshalb muss super(…) die erste Zeile sein.
Ansatz: Aufgerufen wird zuerst der Konstruktor der Klasse, die hinter new steht.
Weiter: Dessen erste Zeile springt in die Oberklasse — erst danach geht es in der Unterklasse weiter.
A6
Wer hat welche Methode?
AFB II
Konto
  • - inhaber: Zeichenkette
  • - kontostand: Fließkommazahl
  • c Konto(inhaber: Zeichenkette)
  • + getInhaber(): Zeichenkette
  • + einzahlen(betrag: Fließkommazahl)
  • + beschreibung(): Zeichenkette
Sparkonto
  • - zinssatz: Fließkommazahl
  • c Sparkonto(inhaber: Zeichenkette, zinssatz: Fließkommazahl)
  • + beschreibung(): Zeichenkette
  • + getZinssatz(): Fließkommazahl
  • + zinsenGutschreiben()

Kreuze für jede Methode an: Hat ein Konto-Objekt sie? Hat ein Sparkonto-Objekt sie? Läuft beim Sparkonto eigener Code aus der Klasse Sparkonto?

Setze die passenden Kreuze. Enter setzt und löscht.
MethodeKontoSpar­kontoeigener Code
getInhaber()
einzahlen(…)
beschreibung()
getZinssatz()
zinsenGutschreiben()
Ein Sparkonto kann alles, was ein Konto kann — und mehr. Umgekehrt gilt das nicht: getZinssatz() gibt es bei einem gewöhnlichen Konto nicht. beschreibung() steht in beiden Karten, ist also überschrieben: Bei einem Sparkonto läuft die Version aus Sparkonto. Geerbte Methoden wie einzahlen laufen dagegen mit dem Code aus Konto.
Ansatz: Der Pfeil zeigt von Sparkonto zu Konto: Sparkonto erbt alles, was in der Konto-Karte steht.
Weiter: Für die dritte Spalte: Steht die Methode (auch) in der Sparkonto-Karte?
A7
Vom Diagramm zum Code: Kinotickets
AFB IIMix

Wiederholung aus 1.2.2 und 1.2.3 (Klassendiagramme, Konstruktoren): Ordne jedem Teil des Diagramms die passende Java-Zeile zu.

Kinoticket
  • - film: Zeichenkette
  • c Kinoticket(film: Zeichenkette)
  • + getFilm(): Zeichenkette
  • + getPreis(): Fließkommazahl
Schuelerticket
  • - schule: Zeichenkette
  • c Schuelerticket(film: Zeichenkette, schule: Zeichenkette)
  • + getPreis(): Fließkommazahl
  • + getSchule(): Zeichenkette
Ansatz: Beginne mit den eindeutigen Paaren: Attribut → private-Zeile, c → Konstruktorkopf.
Weiter: Der Pfeil wird zum Klassenkopf. Und film ist privat in Kinoticket — wie kommt der Wert dorthin?
A8
Wie laut ist die Musikschule?
AFB III
public class Instrument {
    public int dezibel() {
        return 60;
    }

    public int spielen(int minuten) {
        return dezibel() + minuten;
    }
}

public class Trommel extends Instrument {
    @Override
    public int dezibel() {
        return 100;
    }
}

public class Floete extends Instrument {
    @Override
    public int spielen(int minuten) {
        return super.spielen(minuten) - 5;
    }
}
Trommel t = new Trommel();
Floete f = new Floete();
Instrument i = new Instrument();
Rechne die Kette Schritt für Schritt: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
  1. i.spielen(10)
  2. f.spielen(10)
  3. t.spielen(10)
  4. t.dezibel() + f.dezibel()
Die Flöte überschreibt spielen, holt sich aber mit super.spielen(10) erst 70 und zieht 5 ab: 65. Die Trommel überschreibt nur dezibel() — und trotzdem ändert sich spielen: Die geerbte Methode ruft dezibel() auf, und dabei läuft die Methode des Objekts, also die der Trommel: 100 + 10 = 110. Zuletzt: t.dezibel() liefert 100, die Flöte hat dezibel() unverändert geerbt und liefert 60 — zusammen 160. (Mit java geprüft.)
Ansatz: Frage bei jedem Aufruf: Welche Klasse hat das Objekt — und hat diese Klasse die Methode selbst oder nur geerbt?
Weiter: Auch wenn spielen aus Instrument stammt: Der Aufruf dezibel() darin fragt das Objekt, auf dem gerade gespielt wird.
A9
Fehlersuche: Das Familienabo
AFB III

Ein Streamingdienst hat die Oberklasse Streamingabo mit dem privaten Attribut kunde, dem Konstruktor Streamingabo(String kunde), dem Getter getKunde() und der Methode public double preis(). Die Unterklasse lässt sich nicht übersetzen — drei Zeilen sind schuld.

Klicke genau die fehlerhaften Zeilen an — die richtigen musst du stehen lassen.
javac meldet: Zeile 4 cannot find symbol … method Streamingabo(String) (und zusätzlich, dass der Oberklassen-Konstruktor ohne Argument fehlt), Zeile 6/7 method does not override or implement a method from a supertype — hier zeigt sich der Nutzen von @Override: Ohne die Annotation wäre preis(int) still eine neue Methode geworden. Zeile 9: kunde has private access in Streamingabo. (Alle Meldungen mit javac geprüft.)
Ansatz: Prüfe drei Regeln: Wie ruft man den Oberklassen-Konstruktor auf? Was heißt „überschreiben“ genau? Was darf die Unterklasse von der Oberklasse direkt sehen?
Weiter: Vergleiche den Kopf von preis mit dem in der Oberklasse — Zeichen für Zeichen.
A10
Trickaufgabe: Zwei Haushaltsroboter
AFB IIITrick
public class Roboter {
    public String gruss() {
        return "Piep";
    }

    public String vorstellen() {
        return gruss() + "! Ich bin ein Roboter.";
    }
}

public class Putzroboter extends Roboter {
    public String gruss(String name) {
        return "Hallo " + name;
    }
}

public class Rasenroboter extends Roboter {
    @Override
    public String gruss() {
        return "Brumm";
    }
}

Es gilt Putzroboter p = new Putzroboter(); und Rasenroboter r = new Rasenroboter();. Was liefern die Aufrufe?

Wähle in jedem Menü die passende Antwort und klicke dann auf „Prüfen“.

p.gruss() →

p.gruss("Ida") →

p.vorstellen() →

r.vorstellen() →

Der Trick: Putzroboter überschreibt nicht — gruss(String name) hat eine andere Parameterliste und ist eine zusätzliche Methode. Ein Putzroboter hat deshalb zwei gruss-Methoden, und vorstellen() ruft die geerbte ohne Parameter: „Piep“. Der Rasenroboter überschreibt wirklich, also läuft in vorstellen() seine Version. Hätte Putzroboter @Override über seine Methode geschrieben, hätte javac den Denkfehler sofort gemeldet. (Alle Ausgaben mit java geprüft.)
Ansatz: Vergleiche die Köpfe der gruss-Methoden in den drei Klassen. Wo ist die Parameterliste gleich?
Weiter: Nur eine Methode mit gleicher Signatur ersetzt die geerbte. Welche Methode ruft vorstellen() auf — mit oder ohne Parameter?