Programmierung: Vererbung, Polymorphie
auf der Basis von Folien von Volker Gruhn
Michael Goedicke
Michael.goedicke@paluno.uni-due.de
© paluno
Vererbung: Konzept
▪ Konzept der objektorientierten Programmierung
▪ Unterscheidung zwischen Oberklasse (auch Superklasse,
Basisklasse) und Unterklasse (auch Subklasse, abgeleitete Klasse)
▪ Oberklassen vererben Attribute und Methoden an Unterklassen
▪ „ist ein“-Beziehung: Ein Cabrio (Unterklasse) ist ein PKW (Oberklasse)
Notation in UML:
▪ Darstellung durch eine geschlossene, nicht ausgefüllte Pfeilspitze
▪ Pfeilspitze zeigt von der Unterklasse auf die Oberklasse ▪ Vererbte Attribute und Methoden werden in der
Unterklasse i.d.R. nicht zusätzlich angezeigt
PKW
Cabrio
M. Goedicke – Programmierung WiSe 2020/2021
2
© paluno
Vererbung: Konzept
▪ „Erben“: Eine Unterklasse erhält Attribute und Methoden der Oberklasse
▪ „Generalisierung“: Eine Oberklasse ist eine Generalisierung einer oder mehrerer Unterklassen
▪ „Spezialisierung“ und „Ableitung“: Eine Unterklasse ist eine Spezialisierung genau einer Oberklasse bzw. eine Unterklasse leitet sich aus einer Oberklasse ab
▪ „Transitive Vererbungshierarchie“: ▪ Ein Cabrio ist ein PKW.
▪ Ein PKW ist ein KFZ.
➢ Ein Cabrio ist ein KFZ!
KFZ
PKW
Cabrio
M. Goedicke – Programmierung WiSe 2020/2021
3
© paluno
Vererbung: Beispiel
KFZ
▪ LKW
▪ Tankwagen
▪ Lieferwagen ▪ PKW
▪ Cabrio
▪ Geländewagen
Darstellung als disjunkte Teilmengen
LKW
Tank- wagen
Liefer- wagen
KFZ PKW
Cabrio
Gelände- wagen
M. Goedicke – Programmierung WiSe 2020/2021
4
© paluno
Vererbung: Beispiel
Es gibt verschiedene Arten von Versicherungsanträgen ▪ Manche Eigenschaften sind gleich
▪ Z. B. Kennzeichen und Motorleistung des KFZ ▪ Manche Eigenschaften sind speziell
▪ Tankwagen: Tankvolumen (in Litern), Anzahl der Achsen
▪ Lieferwagen: Stauraum, Anzahl der Achsen
▪ Cabrio: Anzahl der Türen, Typ des Verdecks
▪ Geländewagen: Anzahl der Türen, Wattiefe (maximale Tiefe des Wassers, in dem der Geländewagen noch fahren kann)
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
5
© paluno
KFZ
kennzeichen motorleistung
Vererbung: Beispiel
Zusammenfassen von Gemeinsamkeiten
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
6
© paluno
KFZ
kennzeichen motorleistung
Vererbung: Beispiel
Zusammenfassen von Gemeinsamkeiten
LKW
anzahlAchsen
mautBerechnen()
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
7
PKW
© paluno
KFZ
kennzeichen motorleistung
Vererbung: Beispiel
Zusammenfassen von Gemeinsamkeiten
LKW
PKW
anzahlAchsen
mautBerechnen()
Tankwagen
tankvolumen
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
8
© paluno
KFZ
kennzeichen motorleistung
Vererbung: Beispiel
Zusammenfassen von Gemeinsamkeiten
LKW
anzahlAchsen
mautBerechnen()
Tankwagen
tankvolumen
Lieferwagen
stauraum
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
9
PKW
© paluno
KFZ
kennzeichen motorleistung
Vererbung: Beispiel
Zusammenfassen von Gemeinsamkeiten
LKW
anzahlAchsen
mautBerechnen()
Tankwagen
tankvolumen
stauraum
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
10
PKW
anzTueren
Lieferwagen
© paluno
KFZ
kennzeichen motorleistung
Vererbung: Beispiel
Zusammenfassen von Gemeinsamkeiten
LKW
anzahlAchsen
mautBerechnen()
Tankwagen
tankvolumen
Cabrio
verdeckTyp
Lieferwagen
Geländewagen
stauraum
wattiefe
Geländewagen
kennzeichen motorleistung anzTüren wattiefe
Tankwagen
kennzeichen motorleistung anzahlAchsen tankvolumen
mautBerechnen()
Lieferwagen
kennzeichen motorleistung anzahlAchsen stauraum
mautBerechnen()
Cabrio
kennzeichen motorleistung anzTüren verdeckTyp
M. Goedicke – Programmierung WiSe 2020/2021
11
PKW
anzTueren
© paluno
Vererbung: Beispiel
Ergebnis:
KFZ
kennzeichen motorleistung
LKW
anzahlAchsen
anzTueren
mautBerechnen()
Tankwagen
tankvolumen
Cabrio
verdeckTyp
Lieferwagen
Geländewagen
stauraum
wattiefe
M. Goedicke – Programmierung WiSe 2020/2021
12
PKW
© paluno
Vererbung: Vorteile
▪ Vermeidung von doppeltem Programmcode (Redundanz)
▪ Sicherstellung konsistenter Änderungen für alle Unterklassen
▪ Bessere Programmstruktur
▪ Reduktion der Problemkomplexität (mehrstufige Abstraktion)
▪ Vereinfachte Erweiterung von Programmen
▪ Wiederverwendbarkeit
▪ Erlaubt Ausdruck struktureller Unterschiede
▪ Objekte von Unterklassen sind wie Objekte von Oberklassen behandelbar, da sie die entsprechenden Eigenschaften geerbt haben!
M. Goedicke – Programmierung WiSe 2020/2021
13
© paluno
Vererbung in Java
Durch Schlüsselwort extends in der Unterklasse Keine Mehrfachvererbung möglich
public class PKW {
protected int anzTueren;
public int getAnzahlTueren() {
return anzTueren;
}
public class Cabrio extends PKW { private String verdeckTyp; public String getVerdeckTyp() {
}}
return verdeckTyp; }
M. Goedicke – Programmierung WiSe 2020/2021
14
© paluno
Vererbung in Java
Geerbte Attribute & Methoden in Unterklasse verfügbar, als wären sie dort deklariert (Sichtbarkeitsmodifikatoren beachten!)
public class PKW {
protected int anzTueren; public int getAnzahlTueren() {
return anzTueren;
}
public class Cabrio extends PKW {
private String verdeckTyp;
public String getVerdeckTyp() { return verdeckTyp;
} }
}
public static void main(String[] args) {
Cabrio meinCabrio = new Cabrio();
System.out.println(“Türen: ” + meinCabrio.getAnzahlTueren());
System.out.println(“VerdeckTyp: ” + meinCabrio.getVerdeckTyp()); }
M. Goedicke – Programmierung WiSe 2020/2021
15
© paluno
Vererbung in Java
public class KFZ {
protected String kennzeichen; protected int motorleistung;
}
LKW
anzahlAchsen
mautBerechnen()
KFZ
kennzeichen motorleistung
Tankwagen
Lieferwagen
Geländewagen
public class LKW extends KFZ {
protected int anzahlAchsen;
public int mautBerechnen(…){ …
} }
tankvolumen
stauraum
verdeckTyp
wattiefe
public class PKW extends KFZ { protected int anzTueren;
}
public class Tankwagen extends LKW { private int tankvolumen;
}
public class Cabrio extends PKW {
private String verdeckTyp;
}
public class Lieferwagen extends LKW { private int stauraum;
}
public class Gelaendewagen extends PKW { private int wattiefe;
}
PKW
anzTueren
M. Goedicke – Programmierung WiSe 2020/2021
16
Cabrio
© paluno
Vererbung: Abgrenzung zur Assoziation
Assoziation:
▪ „kennt“-Relation
▪ Stellt Kommunikationsbeziehung zwischen Klassen dar
▪ Darstellung der Kommunikationsrichtung durch
spitze, offene Pfeile möglich (z.B. „Klasse B kennt Klasse A, nicht umgekehrt“)
▪ Attribute und Methoden unabhängig definiert
Vererbung:
▪ „ist ein“-Relation
▪ Unterklasse kennt immer die Oberklasse
▪ In der Oberklasse definierte Attribute und Methoden sind implizit in auch der Unterklasse definiert
Klasse A
Klasse B
Klasse B
Oberklasse
Unterklasse
M. Goedicke – Programmierung WiSe 2020/2021
17
Klasse A
© paluno
Vererbung: Zuweisungskompatibilität
Zuweisungen zwischen Instanzen verschiedener Klassen
▪ Cabrio z3 = new Cabrio();
▪ Variable vom Typ Cabrio erhält Referenz auf neue Cabrio-Instanz
▪ PKW auto = new Cabrio();
▪ Variable vom Typ PKW erhält Referenz auf neue Cabrio-Instanz
▪ Legal, denn ein Cabrio hat alle Eigenschaften und Methoden eines PKWs
▪ Aber: auto hat keinen Zugriff mehr auf die speziellen Elemente eines Cabrios!
▪ Cabrio z3 = new PKW();
▪ Illegal: in der Klasse PKW sind nicht alle Elemente deklariert, die für
z3 benötigt werden => kann Schnittstelle nicht erfüllen! ▪ Cabrio z3 = new Tankwagen();
▪ Illegal: Die beiden Klassen haben keine Vererbungsbeziehung zueinander
M. Goedicke – Programmierung WiSe 2020/2021
18
© paluno
Sichtbarkeit von Bezeichnern im Fall der Vererbung
▪ in einer Unterklasse können alle Bezeichner (Attribute, Methoden …) der Oberklasse verwendet werden, wenn
▪ diese mit protected oder public deklariert wurden
▪ oder sie im gleichen Paket liegen und default-Sichtbarkeit haben
class A {
int attrA;
protected char attrA_1; private long attrA_2;
}
class B extends A {
void blabla() {
this.attrA =9; // erlaubt in diesem Fall (s.o. package) this.attrA_1 = ’a’; // erlaubt
attrA_2 = 4l; // verboten
} }
M. Goedicke – Programmierung WiSe 2020/2021
19
© paluno
Vererbung: Redefinieren, Überschreiben, Überladen
Attribute und Methoden können in Unterklassen redefiniert werden Methoden können in Unterklassen überschrieben und überladen werden
Redefinition von Attributen und Methoden:
▪ Attribut wird in Subklasse erneut mit gleichem Namen & Datentyp definiert ▪ Attribut der Oberklasse wird verdeckt
▪ Auch für Methoden möglich, allerdings nicht in Java
Überschreiben von Methoden:
▪ Methode wird in Subklasse erneut mit gleicher Signatur definiert ▪ Methode der Oberklasse wird verdeckt
Überladen von Methoden:
▪ Zusätzliche Definition einer Methode (veränderte Signatur, z. B. Zusätzliche
Parameter, andere Datentypen)
▪ Ist auch innerhalb einer Klasse (ohne Vererbung) möglich
M. Goedicke – Programmierung WiSe 2020/2021
20
© paluno
Vererbung: Redefinieren, Überschreiben
Erneute Definition eines vererbten Attributes bzw. einer vererbten
Methode
▪ Es existieren zwei Definitionen (in der Oberklasse und in der Unterklasse)
▪ Jedes Objekt nutzt die „nächstliegende“ Definition, d. h. die seiner eigenen Klasse oder die einer „nahen“ Oberklasse
Überschreiben/Redefinieren in UML:
Tankwagen
anzahlAchsen tankvolumen
mautBerechnen()
LKW
anzahlAchsen
mautBerechnen()
Der Unterschied zwischen Überschreiben und Redefinieren wird im Kapitel Polymorphie erklärt
M. Goedicke – Programmierung WiSe 2020/2021
21
© paluno
Vererbung: Überschreiben
Überschreiben in Java
Tankwagen
anzahlAchsen tankvolumen
mautBerechnen()
LKW
anzahlAchsen
mautBerechnen()
public class LKW {
protected int anzahlAchsen = 3;
public int mautBerechnen() { …
} }
public class Tankwagen extends LKW { private int anzahlAchsen = 4;
private int tankvolumen;
public int mautBerechnen () { …
}
}
M. Goedicke – Programmierung WiSe 2020/2021
22
© paluno
Vererbung: Überschreiben
Überschreiben in Java
▪ Zugriff auf Attribut / Methode der Oberklasse mittels Schlüsselwort super
Tankwagen
anzahlAchsen tankvolumen
mautBerechnen()
LKW
anzahlAchsen
mautBerechnen()
public class LKW {
protected int anzahlAchsen = 3;
public int mautBerechnen() { …
} }
public class Tankwagen extends LKW { private int anzahlAchsen = 4;
private int tankvolumen;
public int mautBerechnen() {
… }
public void test() { System.out.println(super.anzahlAchsen);
System.out.println(anzahlAchsen);
super.mautBerechnen(); }
}
M. Goedicke – Programmierung WiSe 2020/2021
23
© paluno
Vererbung: Überladen
Zusätzliche Definition einer (vererbten) Methode
▪ Es existieren zwei ähnliche Definitionen einer Methode mit gleichem
Namen aber unterschiedlicher Signatur
▪ Die passende Methode kann anhand der Methodensignatur ausgewählt
werden
Überladen in UML:
Tankwagen
tankvolumen
mautBerechnen(km : int, meter : int)
LKW
anzahlAchsen
mautBerechnen() mautBerechnen(km : int)
M. Goedicke – Programmierung WiSe 2020/2021
24
© paluno
Vererbung: Überladen
Überladen in Java:
▪ Zugriff auf Methode der Oberklasse mittels Schlüsselwort super oder automatische Auswahl der passenden Methoden anhand der Signatur
Tankwagen
tankvolumen
mautBerechnen(km : int, meter : int)
LKW
anzahlAchsen
mautBerechnen() mautBerechnen(km : int)
public class LKW {
protected int anzahlAchsen;
public int mautBerechnen() { return 300 * anzahlAchsen;
}
public int mautBerechnen(int km) { return anzahlAchsen * km * 1000;
} }}
}
public class Tankwagen extends LKW { protected int tankvolumen;
public int mautBerechnen(int km,
int meter) {
return
super.mautBerechnen(km) + anzahlAchsen * meter;
M. Goedicke – Programmierung WiSe 2020/2021
25
© paluno
Vererbung: Konstruktoren
▪ Wiederholung: Wenn eine Java-Klasse keinen eigenen Konstruktor definiert, dann besitzt sie automatisch den Standardkonstruktor:
public class Basis { public class Basis {
}
public Basis() {
super();
} }
▪ Achtung: Wenn eine Java-Klasse einen eigenen Konstruktor definiert, dann besitzt sie nicht automatisch den Standardkonstruktor!
public class Basis {
private int x;
public Basis(int x) {
this.x = x; }
}
kein Standardkonstruktur
M. Goedicke – Programmierung WiSe 2020/2021
26
© paluno
Vererbung: Konstruktoren
▪ In einer abgeleiteten Klasse kann der Konstruktor der Basisklasse mit Hilfe des Schlüsselworts super aufgerufen werden.
public class Basis {
private int x;
public Basis(int x) { this.x = x;
} }
public class Tochter extends Basis { private int y;
public Tochter(int x, int y) {
Aufruf des Superkonstruktors
}
super(x);
▪ Der Aufruf des Superkonstruktors muss die erste Anweisung im Konstruktor der abgeleiteten Klasse sein.
this.y = y; }
M. Goedicke – Programmierung WiSe 2020/2021
27
© paluno
Vererbung: Konstruktoren
▪ Wenn die Klasse Tochter keinen eigenen Konstruktor definiert, dann besitzt sie den Standardkonstruktur, der den Standardkonstruktor der Basisklasse aufruft.
▪ Da die Klasse Basis aber keinen Standardkonstruktur besitzt, tritt in diesem Fall ein Kompilierfehler auf!
public class Basis {
private int x;
public Basis(int x) {
this.x = x;
} }
public class Tochter extends Basis {
public Tochter() {
super();
} }
public class Tochter extends Basis {
}
M. Goedicke – Programmierung WiSe 2020/2021
28
© paluno
Zusammenfassung
Vererbung
▪ Ableiten von Oberklassen als Mittel zur Wiederverwendung ▪ Vererbung in UML
▪ Vererbung in Java
▪ Überschreiben von Attributen
▪ Überladen, Überschreiben von Methoden ▪ Schlüsselwortsuper
KFZ
kennzeichen motorleistung
LKW
anzahlAchsen
anzTueren
mautBerechnen()
Tankwagen
tankvolumen
Cabrio
verdeckTyp
Lieferwagen
Geländewagen
stauraum
wattiefe
M. Goedicke – Programmierung WiSe 2020/2021
29
PKW
© paluno
Abstrakte Klassen
▪ Idee und Konzept
▪ Verbot der direkten Instanziierung von Klassen
→Abstrakte Klassen
▪ Zur Modellierung von „Ist-Art-von-Beziehung“ in
Vererbungshierarchien
▪ Zwang zur Implementierung von Methoden in Unterklassen
→Abstrakte Methoden in abstrakten Klassen
▪ Oberklassen soll Methoden vorgeben, jedoch nicht implementieren
Instanzen verboten!
KFZ
LKW
PKW
Tankwagen
Lieferwagen
Cabrio
Instanzen erlaubt!
Geländewagen
M. Goedicke – Programmierung WiSe 2020/2021
30
© paluno
Abstrakte Klassen
▪ Abstrakte Klassen in UML
▪ Klassenname kursiv = Abstrakte Klasse
▪ Abstrakte Klassen haben alle Eigenschaften von konkreten Klassen
▪ Alle abstrakten Klassen haben Unterklassen oder das Design ist nicht vollständig
Instanzen verboten!
KFZ
LKW
PKW
Tankwagen
Lieferwagen
Cabrio
Instanzen erlaubt!
Geländewagen
M. Goedicke – Programmierung WiSe 2020/2021
31
© paluno
Abstrakte Klassen
▪ Abstrakte Methoden in UML
▪ Methodenname kursiv = Abstrakte Methode ▪ Abstrakte Methoden geben die Signatur vor
▪ Name, Parameterliste
▪ Klassen mit abstrakten Methoden sind immer auch abstrakte Klassen
▪ Abstrakte Klassen können auch konkrete Methoden implementieren
Lieferwagen
stauraum
beladeFrachtraum()
Tankwagen
tankvolumen
beladeFrachtraum()
LKW
anzahlAchsen
beladeFrachtraum()
M. Goedicke – Programmierung WiSe 2020/2021
32
© paluno
Abstrakte Klassen in Java
public abstract class LKW { …
public abstract void beladeFrachtraum(); kein
Methodenrumpf
LKW
anzahlAchsen
beladeFrachtraum ()
}
Lieferwagen
stauraum
beladeFrachtraum()
public class Lieferwagen extends LKW { …
public void beladeFrachtraum() { …
} }
Wenn eine Klasse abstrakte Methoden enthält, muss die ganze Klasse als abstrakt deklariert werden!
M. Goedicke – Programmierung WiSe 2020/2021
33
© paluno
Abstrakte Klassen in Java
public abstract class LKW {
protected int anzahlAchsen;
public abstract void beladeFrachtraum();
}
public class Tankwagen extends LKW { private int tankvolumen;
public void beladeFrachtraum() {
System.out.println(“Der Tankwagen wurde mit ” + tankvolumen + ” Litern Flüssigkeit befüllt”);
} }
public class Lieferwagen extends LKW { private int stauraum;
public void beladeFrachtraum() {
System.out.println(“Der Lieferwagen wurde mit Kisten des Volumens ” + stauraum + ” Litern beladen”);
} }
LKW
anzahlAchsen
beladeFrachtraum()
Tankwagen
tankvolumen
beladeFrachtraum()
Lieferwagen
stauraum
beladeFrachtraum()
M. Goedicke – Programmierung WiSe 2020/2021
34
© paluno
Polymorphie
▪ Überladen: Methoden der Klasse selbst oder einer Oberklasse werden mit veränderten Parametern neu definiert.
▪ Die Methodensignatur unterscheidet sich => keine Polymorphie! ▪ Die passende Methode wird schon zur Compile-Zeit ausgewählt
▪ Implementieren: Abstrakte Methoden der Oberklasse werden in der Subklasse ausimplementiert
▪ Überschreiben: Methoden der Oberklasse werden in der Subklasse erneut mit gleicher Signatur definiert (die Methode der Oberklasse bleibt aber mittels super zugreifbar)
▪ Redefinition: Methoden der Oberklasse werden in der Subklasse erneut mit gleicher Signatur definiert und vollständig überdeckt
▪ In Java nicht möglich, alle Methoden sind virtuell und werden immer überschrieben. Eine Methode nennt man virtuell, wenn erst zur Laufzeit ermittelt wird, welche Variante genau ausgeführt wird.
M. Goedicke – Programmierung WiSe 2020/2021
35
© paluno
Polymorphie
▪ Ziele und Konsequenzen
▪ Anpassung von Unterklassen an Besonderheiten der Spezialisierung
▪ Methode liegt in mehreren Gestalten vor => Polymorphie
▪ Jedes Objekt nutzt die „nächstliegende“ Definition, d. h. die seiner eigenen Klasse oder die einer „nahen“ Oberklasse
▪ Bei Polymorphie bestimmt der Objekttyp die Methode ▪ Technisch durch „dynamisches Binden“ realisiert
➢ Die passende Methode wird zur Laufzeit ausgewählt
▪ Bei nicht-virtuellen Methoden bestimmt der Variablentyp die Methode ▪ Die passende Methode wird schon zur Compile-Zeit ausgewählt
▪ Die passende Überladung wird ebenfalls zur Compile-Zeit ausgewählt ▪ Überladungen können virtuell sein (in Java immer der Fall), womit zur
Laufzeit weiter ausgewählt wird
M. Goedicke – Programmierung WiSe 2020/2021
36
© paluno
Polymorphie: Beispiel (Implementieren)
▪ berechneMietpreis von KFZ: ▪ Abstrakt, nicht implementiert
▪ berechneMietpreis von Tankwagen ▪ 3000 + tankvolumen ∙ 2
▪ berechneMietpreis von Lieferwagen: ▪ 1000 + stauraum
LKW
anzahlAchsen
KFZ
berechneMietpreis()
M. Goedicke – Programmierung WiSe 2020/2021
37
Tankwagen
tankvolumen
berechneMietpreis()
Lieferwagen
stauraum
berechneMietpreis()
© paluno
Polymorphie: Beispiel (Implementieren)
public abstract class KFZ {
public abstract int berechneMietpreis ();
… }
public class Tankwagen extends LKW { public int berechneMietpreis () {
// ergebnis = 3000 + 2 x tankvolumen
}
… }
public class Lieferwagen extends LKW { public int berechneMietpreis () {
// ergebnis = 1000 + stauraum
}
… }
Signatur (Name und Parameter) und Rückgabewert müssen übereinstimmen!
M. Goedicke – Programmierung WiSe 2020/2021
38
© paluno
Polymorphie: Beispiel (Implementieren)
KFZ kfz1 = new Tankwagen(); KFZ kfz2 = new Lieferwagen();
LKW lkw1 = new Tankwagen();
LKW lkw2 = new Lieferwagen();
Tankwagen tawa = new Tankwagen();
Lieferwagen liwa = new Lieferwagen();
kfz1.berechneMietpreis(); kfz2.berechneMietpreis(); lkw1.berechneMietpreis(); lkw2.berechneMietpreis(); tawa.berechneMietpreis(); liwa.berechneMietpreis();
Welche Implementierung aufgerufen wird ermittelt die Java-Laufzeitumgebung
Tankwagen
LKW
anzahlAchsen
tankvolumen
KFZ
berechneMietpreis()
berechneMietpreis()
Lieferwagen
stauraum
berechneMietpreis()
M. Goedicke – Programmierung WiSe 2020/2021
39
© paluno
Polymorphie: Beispiel (Implementieren)
KFZ kfz1 = new Tankwagen(); KFZ kfz2 = new Lieferwagen();
LKW lkw1 = new Tankwagen();
LKW lkw2 = new Lieferwagen();
Tankwagen tawa = new Tankwagen();
Lieferwagen liwa = new Lieferwagen();
kfz1.berechneMietpreis(); Tankwagen::berechneMietpreis() kfz2.berechneMietpreis(); Lieferwagen::berechneMietpreis() lkw1.berechneMietpreis(); Tankwagen::berechneMietpreis() lkw2.berechneMietpreis(); Lieferwagen::berechneMietpreis() tawa.berechneMietpreis(); Tankwagen::berechneMietpreis() liwa.berechneMietpreis(); Lieferwagen::berechneMietpreis()
Tankwagen
LKW
anzahlAchsen
tankvolumen
KFZ
berechneMietpreis()
berechneMietpreis()
Lieferwagen
stauraum
berechneMietpreis()
M. Goedicke – Programmierung WiSe 2020/2021
40
© paluno
Polymorphie
▪ Mit dem Operator instanceof kann ein expliziter Test auf Klassenzugehörigkeit formuliert werden:
if(kfz1 instanceof Lieferwagen)
{
//… }
else if(kfz1 instanceof Tankwagen) {
//… }
else
{ //…
}
LKW
anzahlAchsen
KFZ
berechneMietpreis()
M. Goedicke – Programmierung WiSe 2020/2021
41
Tankwagen
tankvolumen
berechneMietpreis()
Lieferwagen
stauraum
berechneMietpreis()
© paluno
Polymorphie
▪ In Java erbt jede Klasse implizit von der Klasse Object. public class A extends Object { public class A {
}}
kann weggelassen werden
▪ Die Klasse Object bildet also immer die eindeutige Wurzel der Vererbungshierachie:
Object
A
B
C
D
M. Goedicke – Programmierung WiSe 2020/2021
42
© paluno
Polymorphie
▪ Durch die Ableitung von Object besitzt jede Klasse einige nützliche Methoden, die in der Regel überschrieben werden:
Object
equals(other:Object):boolean hashCode():int toString():String
.. .
▪ Die equals()-Methode wird verwendet, um das aktuelle Objekt mit dem übergebenen Objekt auf Gleichheit zu prüfen.
▪ Diese Methode muss überschrieben werden, wenn dynamische Datenstrukturen wie Listen verwendet werden.
▪ Wie würde dies für die Liste konkret aussehen?
M. Goedicke – Programmierung WiSe 2020/2021
43
© paluno
Polymorphie
▪ Die hashCode()-Methode sollte überschrieben werden, wenn die equals()-Methode überschrieben wird.
▪ Diese Methode berechnet einen Zahlenwert (z.B. eine Art „Quersumme“), der in Datenstrukturen verwendet wird, die auf einem Hashverfahren basieren, z.B. in Hashtabellen.
▪ Solche Datenstrukturen garantieren schnelle Zugriffszeiten, sofern die hashCode()-Methode geeignet überschrieben wurde.
▪ Hashtabellen werden später besprochen.
Rückgabewert der hashCode()-Methode
von Objekt A
Speicheradresse von Objekt A
Zwei Objekte mit dem selben Hashcode
12315
12316
12317
@4215
@3354
@3423
@9821
M. Goedicke – Programmierung WiSe 2020/2021
44
© paluno
Polymorphie
▪ Die toString()-Methode muss überschrieben werden, wenn eine textuelle Repräsentation des Objekts verlangt wird.
▪ Diese Methode wird implizit aufgerufen, wenn ein String-Literal mit einem Objekt konkateniert werden soll:
TolleKlasse tollesObjekt = new TolleKlasse();
String test = ′′Ich bin ein Literal ′′ + tollesObjekt;
TolleKlasse tollesObjekt = new TolleKlasse();
String test = ′′Ich bin ein Literal ′′ + tollesObjekt.toString();
▪ Die toString()-Methode wird außerdem aufgerufen, wenn ein Objekt der Methode System.out.println(Object object) übergeben wird.
TolleKlasse tollesObjekt = new TolleKlasse(); System.out.println(tollesObjekt);
das macht der Java-Compiler automatisch!
M. Goedicke – Programmierung WiSe 2020/2021
45
© paluno
Polymorphie
public class Test {
public static void schreibe(Object object) { String text = object.toString();
System.out.println(text);
}
}
public class A { }
public class B {
public String toString() {
return ′′Ich bin eine Instanz von Klasse B.′′;
} }
Die Variable object hat den Datentyp Object.
Die Klasse A erbt die toString()-Methode von der Klasse Object.
Die Klasse B überschreibt die toString()-Methode aus der Klasse Object.
M. Goedicke – Programmierung WiSe 2020/2021
46
© paluno
Polymorphie
▪ Obwohl der Parameter der schreibe()-Methode den Datentyp Object hat, wird nicht die toString()-Methode der Klasse Object aufgerufen:
main()-Methode
A a = new A();
B b = new B();
Test.schreibe(a);
Test.schreibe(b);
Konsole
A@50fc5408
Ich bin eine Instanz von Klasse B.
Methode nicht überschrieben Methode überschrieben
▪ Bemerkung: Wenn die toString()-Methode nicht überschrieben wird, dann besteht der Rückgabewert aus dem Klassennamen des Objekts und seiner Speicheradresse als Hexadezimalzahl.
M. Goedicke – Programmierung WiSe 2020/2021
47
© paluno