MINT lernen

Übungen: Vererbung

Ein LKW ist ein Fahrzeug, ein Welpe ist ein Hund — und ein Compiler sieht manchmal weniger als du.

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
Was hat ein LKW?
AFB I

Ein Fuhrparkprogramm ist wie abgebildet modelliert. Nennen Sie alle Attribute und Methoden, die ein Objekt der Klasse LKW besitzt — geerbte eingeschlossen.

Fahrzeug
  • - kennzeichen: Zeichenkette
  • - kmStand: Ganzzahl
  • c Fahrzeug(k: Zeichenkette)
  • + fahren(km: Ganzzahl)
  • + beschreibung(): Zeichenkette
  • + maut(km: Ganzzahl): Ganzzahl
PKW
  • - sitze: Ganzzahl
  • c PKW(k: Zeichenkette, sitze: Ganzzahl)
LKW
  • - nutzlast: Fließkommazahl
  • c LKW(k: Zeichenkette, nutzlast: Fließkommazahl)
  • + beladen(t: Fließkommazahl)
  • + beschreibung(): Zeichenkette
  • + maut(km: Ganzzahl): Ganzzahl
Mehrere Antworten sind richtig. Markiere alle zutreffenden und klicke dann auf „Auswahl prüfen“.
Ein LKW erbt alles aus Fahrzeug (kennzeichen, kmStand, fahren, …) und hat zusätzlich nutzlast und beladen. sitze gehört nur zum PKW — Geschwisterklassen erben nichts voneinander. Konstruktoren werden überhaupt nicht vererbt. Dass kennzeichen privat ist, ändert nichts daran, dass jedes LKW-Objekt dieses Attribut besitzt; nur der Quelltext von LKW darf nicht direkt darauf zugreifen.
Ansatz: Gehe vom LKW aus nach oben: Alles in der Oberklasse gehört auch dem LKW.
Weiter: Der PKW ist ein Geschwister, kein Vorfahre des LKW.
A2
Stimmt's? — Die Bank
AFB I

Entnehmen Sie dem Klassendiagramm einer Bank, welche Aussagen zutreffen.

Konto
  • - inhaber: Zeichenkette
  • # kontostand: Fließkommazahl
  • c Konto(inhaber: Zeichenkette)
  • + einzahlen(b: Fließkommazahl)
  • + abheben(b: Fließkommazahl): Wahrheitswert
Girokonto
  • - dispo: Fließkommazahl
  • + abheben(b: Fließkommazahl): Wahrheitswert
Sparkonto
  • - zinssatz: Fließkommazahl
  • + verzinsen()
5 Aussagen nacheinander. Eine falsche Einschätzung reicht — dann startest du die Serie mit „Neue Runde“ neu.
Aussage 1 von 5

Beim Lesen eines Vererbungsdiagramms helfen drei Fragen: Wo sitzt das Dreieck (dort ist die Oberklasse)? Was steht doppelt (das wird überschrieben)? Welches Zeichen steht vor dem Attribut (- nur die Klasse selbst, # auch Unterklassen, + alle)?
Ansatz: Das Dreieck zeigt zur allgemeineren Klasse.
Weiter: Achte auf das Zeichen vor jedem Attribut: -, # oder +.
A3
ist ein oder hat ein?
AFB I

Ordnen Sie jedes Klassenpaar der passenden Beziehung zu. Die erste Klasse ist jeweils die, von der die Beziehung ausgeht.

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).
1Vererbung („ist ein“)
2Assoziation („hat“, „kennt“)
Der Test ist ein Satz: „Ein Hund ist ein Tier“ passt, also Vererbung. „Ein Auto ist ein Motor“ ist Unsinn — ein Auto hat einen Motor, also Assoziation. Wer bei „Fußballteam – Spieler“ an Vererbung denkt, verwechselt „besteht aus“ mit „ist ein“.
Ansatz: Bilde für jedes Paar den Satz „Ein … ist ein …“.
Weiter: Klingt der Satz falsch, probiere „Ein … hat / kennt …“.
A4
Der LKW in Java
AFB II

Implementieren Sie die Klasse LKW aus A1 (ohne beladen und maut). beschreibung() soll die Beschreibung der Oberklasse um die Nutzlast ergänzen. Drei 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 LKW Fahrzeug {
    private double nutzlast;
    public LKW(String kennzeichen, double nutzlast) {
        (kennzeichen);
        .nutzlast = nutzlast;
    }
    
    public String beschreibung() {
        return + ", Nutzlast " + nutzlast + " t";
    }
}

Der Konstruktor gibt das Kennzeichen mit super(kennzeichen) an die Oberklasse weiter — die privaten Attribute von Fahrzeug kann nur deren Konstruktor setzen. beschreibung() ohne super. würde sich selbst aufrufen und endlos laufen (StackOverflowError). Ergebnis nach 80 km: "H-XY 1, 80 km, Nutzlast 12.0 t".
Ansatz: Vererbung wird mit einem Schlüsselwort im Klassenkopf angezeigt; der Oberklassen-Konstruktor heißt in der Unterklasse nicht „Fahrzeug“.
Weiter: Die Beschreibung der Oberklasse erreichst du mit super. vor dem Methodennamen — ohne ruft die Methode sich selbst auf.
A5
Maut für den ganzen Fuhrpark
AFB II Mix

In Fahrzeug gilt maut(km) = km * 2 (Cent). LKW überschreibt: return km * 5 + super.maut(km); — PKW überschreibt nicht. Bestimmen Sie die Werte.

ArrayList<Fahrzeug> fuhrpark = new ArrayList<Fahrzeug>();
fuhrpark.add(new PKW("H-A 1", 5));
fuhrpark.add(new LKW("H-B 2", 7.5));
fuhrpark.add(new LKW("H-C 3", 18));
int summe = 0;
for (int i = 0; i < fuhrpark.size(); i++) {
    summe = summe + fuhrpark.get(i).maut(100);
}
Arbeite die Kette Schritt für Schritt ab: Erst wenn ein Schritt stimmt, wird der nächste freigeschaltet. Enter prüft.
  1. fuhrpark.get(0).maut(100) Cent
  2. fuhrpark.get(1).maut(100) Cent
  3. summe nach der Schleife Cent
  4. dieselbe Summe, wenn vorher fuhrpark.set(0, fuhrpark.get(1)); ausgeführt wird Cent
Die Liste hat den Typ Fahrzeug, trotzdem läuft für jeden Eintrag die Methode seines Objekts: 200 für den PKW (geerbt), je 500 + 200 = 700 für die LKW — zusammen 1600. Nach set(0, get(1)) zeigt Index 0 auf dasselbe LKW-Objekt wie Index 1 (aus 4.3.1: Liste speichert Referenzen), also 3 · 700 = 2100.
Ansatz: Frage bei jedem Eintrag: Von welcher Klasse ist das Objekt — und überschreibt diese Klasse maut?
Weiter: super.maut(km) im LKW ruft die Fahrzeug-Version auf: 2 Cent je km kommen zu den 5 Cent dazu.
A6
Was passiert bei new Girokonto(…)?
AFB II

Für die Bank aus A2 gilt: Girokonto(inhaber, dispo) ruft zuerst super(inhaber) auf und setzt dann dispo. Stellen Sie den Ablauf von Girokonto g = new Girokonto("Ada", 500); in der richtigen Reihenfolge dar.

Ziehe die Karten in die richtige Reihenfolge — mit der Tastatur: ↑/↓ verschiebt, Shift+↑/↓ wechselt nur den Fokus.
1Speicher für ein Girokonto-Objekt mit allen geerbten und eigenen Attributen wird angelegt.
2Der Konstruktor von Girokonto wird mit "Ada" und 500 aufgerufen.
3super("Ada") ruft den Konstruktor von Konto auf.
4Konto setzt inhaber auf "Ada" und kontostand auf 0.
5Zurück in Girokonto: dispo wird 500.
6Die Referenz auf das fertige Objekt wird in g gespeichert.
Es entsteht ein Objekt, das die Attribute beider Klassen enthält — nicht ein Konto- und zusätzlich ein Girokonto-Objekt. Der Oberklassen-Konstruktor läuft mitten im Unterklassen-Konstruktor, und zwar als Erstes; deshalb kann die Unterklasse sich darauf verlassen, dass die geerbten Attribute schon gesetzt sind.
Ansatz: Wie viele Objekte entstehen — eins oder zwei?
Weiter: super(…) ist die erste Anweisung im Konstruktor der Unterklasse.
A7
Wer bellt hier?
AFB II

Tier.laut() liefert "(still)", Hund überschreibt mit "Wuff", Welpe extends Hund überschreibt mit return super.laut() + "chen";, Katze überschreibt mit "Miau". Ermitteln Sie die Rückgabe jedes Aufrufs.

Ansatz: Schau bei jedem Aufruf nur auf das, was hinter new steht.
Weiter: super im Welpen meint die direkte Oberklasse Hund, nicht Tier.
A8
Fehlersuche: Die Aushilfe
AFB III

Mitarbeiter hat die privaten Attribute name und gehalt sowie getGehalt(). Eine Aushilfe ist ein Mitarbeiter und bekommt das halbe Gehalt. Überprüfen Sie die Klasse — drei Zeilen lassen sich nicht übersetzen.

In diesem Text stecken Fehler. Klicke genau die falschen Zeilen an — die richtigen musst du stehen lassen.
Alle drei Fehler sind typische Klausurfehler: Mehrfachvererbung gibt es in Java nicht, super(…) muss die erste Anweisung sein, und private Attribute der Oberklasse sind in der Unterklasse nicht sichtbar. Beachte: Zeile 4 ist für sich richtig — falsch ist nur die Position von Zeile 5.
Ansatz: Prüfe Klassenkopf, Konstruktor und die überschreibende Methode einzeln.
Weiter: Drei Regeln: eine Oberklasse, super zuerst, - bleibt privat.
A9
Abheben mit Dispo
AFB III

Ein normales Konto darf nicht ins Minus. Ein Girokonto darf bis zu seinem Dispo überzogen werden (dispo = 500 heißt: bis −500 €). Erweitern Sie Girokonto um die überschreibende Methode — kontostand ist in Konto mit # (protected) deklariert.

Wähle in jedem Menü den passenden Eintrag und prüfe dann alle auf einmal.
@Override
public boolean abheben(double betrag) {
    if (kontostand - betrag  ) {
        kontostand = kontostand  betrag;
        return ;
    }
    return false;
}
Neuer Stand kontostand - betrag darf nicht unter -dispo fallen, also >= -dispo. Test: 0 € Guthaben, 500 € Dispo — 300 € abheben klappt (−300), weitere 250 € nicht (wäre −550). Weil kontostand protected ist, darf die Unterklasse direkt rechnen; wäre es privat, bräuchte man einen Setter oder super.abheben.
Ansatz: Schreibe die Bedingung zuerst in Worten: „Der neue Kontostand ist mindestens minus Dispo.“
Weiter: dispo ist positiv gespeichert, die Grenze liegt also bei -dispo.
A10
Trickaufgabe: Was der Compiler sieht
AFB III Trick

Gegeben sind die Klassen aus A1 (beladen gibt es nur in LKW). Entscheiden Sie für jede Zeile, was passiert.

Wähle für jede Zeile eine Stufe: 0 = Übersetzungsfehler, 1 = Laufzeitfehler, 2 = läuft fehlerfrei. Mit der Tastatur: Tab zur Zeile, ←/→ zwischen den Stufen, Enter setzt.
0 = Übersetzungsfehler2 = läuft fehlerfrei
Fahrzeug f = new LKW("H-A 1", 12);
LKW l = new Fahrzeug("H-B 2");
Fahrzeug f = new LKW("H-A 1", 12); f.beladen(3);
Fahrzeug f = new PKW("H-P 1", 5); LKW l = (LKW) f;
Fahrzeug f = new LKW("H-A 1", 12); f.fahren(50);
Der Trick steckt in Zeile 3: Das Objekt ist ein LKW, aber der Compiler kennt nur den Typ der Variable — und Fahrzeug hat kein beladen. Zeile 2 scheitert, weil nicht jedes Fahrzeug ein LKW ist. Zeile 4 übersetzt dank der Typumwandlung, bricht aber zur Laufzeit mit einer ClassCastException ab: Ein PKW lässt sich nicht in einen LKW verwandeln.
Ansatz: Der Compiler prüft nur die Typen der Variablen, nicht die Objekte.
Weiter: Eine Zuweisung „nach oben“ (LKW → Fahrzeug) geht immer, „nach unten“ nie ohne Umwandlung.