Ü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.
Vererbung passt nur, wenn jedes Objekt der Unterklasse auch ein Objekt der Oberklasse ist. Welche Klassenköpfe sind sinnvoll modelliert?
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.extends steht immer das Allgemeinere.In einer Messenger-App gilt class Sprachnachricht extends Nachricht. Die Oberklasse hat das private Attribut absender und den öffentlichen Getter getAbsender().
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.@Override ist eine Annotation — ein Hinweis an den Compiler, kein Muss.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;
}
}
groesseKB() = 192. Auch das private Attribut absender ist geerbt: Es steckt im Objekt und wird über super(absender) gesetzt. (Mit java geprüft.)Nachricht, nur in Sprachnachricht — oder in beiden?@Override markiert die überschriebenen Methoden.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.
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.)super. ruft die gleichnamige Methode der Oberklasse.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).
Sparkonto startet mit "Ida" und 1.5.
super("Ida") ruft den Konstruktor von Konto auf.
Konto setzt inhaber auf "Ida"; kontostand bleibt 0.0.
Sparkonto: zinssatz wird 1.5.
s verweist auf das fertige Objekt — mit inhaber, kontostand und zinssatz.
super(…) die erste Zeile sein.new steht.- - inhaber: Zeichenkette
- - kontostand: Fließkommazahl
- c Konto(inhaber: Zeichenkette)
- + getInhaber(): Zeichenkette
- + einzahlen(betrag: Fließkommazahl)
- + beschreibung(): Zeichenkette
- - 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?
| Methode | Konto | Sparkonto | eigener Code |
|---|---|---|---|
getInhaber() |
|||
einzahlen(…) |
|||
beschreibung() |
|||
getZinssatz() |
|||
zinsenGutschreiben() |
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.Wiederholung aus 1.2.2 und 1.2.3 (Klassendiagramme, Konstruktoren): Ordne jedem Teil des Diagramms die passende Java-Zeile zu.
- - film: Zeichenkette
- c Kinoticket(film: Zeichenkette)
- + getFilm(): Zeichenkette
- + getPreis(): Fließkommazahl
- - schule: Zeichenkette
- c Schuelerticket(film: Zeichenkette, schule: Zeichenkette)
- + getPreis(): Fließkommazahl
- + getSchule(): Zeichenkette
film und getFilm() werden geerbt und nicht wiederholt. Taucht eine Methode wie getPreis() in beiden Karten auf, wird sie überschrieben. (Klassen mit javac geprüft.)private-Zeile, c → Konstruktorkopf.film ist privat in Kinoticket — wie kommt der Wert dorthin?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();
-
i.spielen(10) -
f.spielen(10) -
t.spielen(10) -
t.dezibel() + f.dezibel()
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.)spielen aus Instrument stammt: Der Aufruf dezibel() darin fragt das Objekt, auf dem gerade gespielt wird.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.
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.)preis mit dem in der Oberklasse — Zeichen für Zeichen.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?
p.gruss() →
p.gruss("Ida") →
p.vorstellen() →
r.vorstellen() →
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.)gruss-Methoden in den drei Klassen. Wo ist die Parameterliste gleich?vorstellen() auf — mit oder ohne Parameter?