19.12.13
Vorlesung „Programmieren“
Vererbung und Polymorphismus
Prof. Dr. Stefan Fischer
Institut für Telematik, Universität zu Lübeck
http://www.itm.uni-luebeck.de/people/fischer
Bisher: Klassen und Objekte
• Haupteigenschaften: Abstraktion und Kapselung
• Abstraktion
– Klassen stellen die benötigen Methoden zur Verfügung
– Attribute werden (idealerweise) ausschließlich über Methodenaufrufe
verändert
– Interne Funktionsweise wird versteckt
• Kapselung (data hiding)
– Daten und Funktionen bilden eine integrale Einheit
– Kapselung ist das Ergebnis der Abstraktion
• Beispiel: Klasse „Punkt“
– Beispiel: Punkt (rotiere und verschiebe)
– Nach außen ist nur die Schnittstelle sichtbar, nicht die Attribute
Security - 04 Cryptology
#2
Was ist mit ähnlichen Klassen?
• Beispiel: Klassen „Auto“ und „Bus“
• Haben einige gemeinsame Attribute
–
–
–
–
Hersteller
Wechselintervall
Gefahrene Kilometer
Baujahr
• Aber auch Unterschiede
– Auto: Cabriodach, ...
– Bus: Toilette, ...
Bildquelle (Porsche): Oliver Kurmis, http://de.wikipedia.org/w/index.php?title=Datei:1962_Porsche_911.jpg&filetimestamp=20100321221316
Security - 04 Cryptology
#3
1
19.12.13
Was ist mit ähnlichen Klassen?
• Bisherige Lösungsoptionen
– Option 1: Implementieren zweier getrennter Klassen
– Option 2: Implementieren einer gemeinsamen Klasse mit allen Attributen von
Auto und Bus
• Beides ist nicht wirklich schön
– Wird das Programm korrigiert oder verändert, müssen unter Umständen alle
Klassen angepasst werden
• Lösung: Vererbung
Bildquelle (Porsche): Oliver Kurmis, http://de.wikipedia.org/w/index.php?title=Datei:1962_Porsche_911.jpg&filetimestamp=20100321221316
Security - 04 Cryptology
#4
Vererbung
Vererbung
• Man versucht, zu ähnlichen Klassen eine
gemeinsame Oberklasse zu finden
• Fasst Ähnlichkeiten zusammen
– In Form von Attributen, Verhalten (Methoden),
Beziehungen zu anderen Klassen
• Ergänzt in den Unterklassen lediglich die
Unterschiede
– Ergänzende Attribute, Methoden, Beziehungen zu
anderen Klassen
5-2-6
2
19.12.13
Vererbung
• Gemeinsamkeiten ähnlicher Klassen werden zu einer
Oberklasse zusammengefasst
Fahrzeug
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
wechsleOel()
Gemeinsame
Oberklasse
Bus
PKW
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
toilette: boolean
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
Bauart: String
Gemeinsamkeiten
wechsleOel()
oeffneDach() : boolean
wechsleOel()
leereToilette()
5-2-7
Vererbung: Grafische Notation
• Unterklassen zeigen auf Oberklasse
Fahrzeug
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
wechsleOel()
Bus
PKW
bauart: String
toilette: boolean
leereToilette()
oeffneDach(): boolean
5-2-8
Vererbung: Ausdrucksweise
• Fahrzeug ist Oberklasse (Superclass) bzw. Generalisierung von Bus und
PKW
• Bus und PKW sind Unterklassen (Subclasses) bzw. Spezialisierungen von
Fahrzeug
Fahrzeug
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
wechsleOel()
Bus
toilette: boolean
leereToilette()
PKW
bauart: String
oeffneDach(): boolean
5-2-9
3
19.12.13
Vererbung: Ausdrucksweise
• Pfeile deuten eine „ist ein“-Beziehung an
Bus „ist ein“ Fahrzeug
Aber: nicht jedes
Fahrzeug
ist ein Bus
Fahrzeug
PKW „ist ein“ Fahrzeug
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
Aber: nicht jedes
Fahrzeug
ist ein PKW
wechsleOel()
Bus
PKW
bauart: String
toilette: boolean
leereToilette()
oeffneDach(): boolean
5-2-10
Vererbung
• Unterklassen erben von ihrer Oberklasse
– Erben alle Attribute und Methoden
– Kann Oberklasse um weitere Attribute und Methoden
ergänzen
• Erben bedeutet
– Attribute und Methoden der Oberklasse können in der
Unterklasse verwendet werden
– Aus Sicht der Unterklasse wirkt es, als wären sie in der
Unterklasse selbst definiert
5-2-11
Vererbung in Java
• Vererbung wird über Schlüsselwort
extends angegeben
Fahrzeug
...
– Man kann von genau einer Oberklasse erben
– Andere Programmiersprachen erlauben
auch von mehreren Oberklassen zu erben (C
++, ...)
• Syntax: class Unterklasse extends Oberklasse {...} ...
Bus
PKW
...
...
...
...
• Beispiel
– class Bus extends Fahrzeug {...} – class PKW extends Fahrzeug {...} 5-2-12
4
19.12.13
Vererbungshierarchie
• Vererbung kann auch über mehrere
Hierarchiestufen erfolgen
Gegenstand
– Vererbung von Attributen und Methoden erfolgt
transitiv
...
...
• Beispiel
Fahrzeug
– Fahrzeug erbt alles von Gegenstand
– Bus und PKW erben alles von Fahrzeug
und damit auch alles von Gegenstand
• Umsetzung in Java
– class Fahrzeug extends Gegenstand {...} – class Bus extends Fahrzeug {...} – class PKW extends Fahrzeug {...}
...
...
Bus
PKW
...
...
...
...
5-2-13
Vererbung in Java
Object
...
• In Java gibt es eine Oberklasse aller Klassen
– java.lang.Object ...
Gegenstand
...
• Wenn keine Oberklasse angegeben ist, wird
Object automatisch zur Oberklasse
– Konsequenz: java.lang.Object ist
Oberklasse jeder Klasse
– Vielleicht nicht direkt, aber irgendwann auf
jeden Fall
• Dies ist nicht in allen Programmiersprachen so
– z.B. nicht in C++
...
Fahrzeug
...
...
Bus
PKW
...
...
...
...
Security - 04 Cryptology
#14
Vererbung und Instanzen
• Von jeder Klasse können Instanzen erzeugt werden
• Diese können ganz normal verwendet werden
• Beispiele
– Fahrzeug f = new Fahrzeug(); f.wechsleOel(); Fahrzeug
...
– Bus b = new Bus(); b.wechsleOel(); b.leereToilette(); ...
– PKW p = new PKW(); p.wechsleOel(); p.oeffneDach(); Security - 04 Cryptology
Bus
PKW
...
...
...
...
#15
5
19.12.13
Vererbung und Instanzen: Darstellung
•
•
Syntax: Instanzname: Klassenname Syntax (Attribute): Attributname = Wert f: Fahrzeug
hersteller = "Honda"
wechselintervall = 5000
km_gefahren = 542
baujahr = 2003
Fahrzeug
hersteller: String
wechselintervall: int
km_gefahren: int
baujahr: int
b: Bus
wechsleOel()
hersteller = "MAN"
wechselintervall = 20000
km_gefahren = 4243
baujahr = 1999
toilette = true
Instanziierung
Bus
PKW
leereToilette()
p: PKW
bauart: String
toilette: boolean
hersteller = "VW"
wechselintervall = 10000
km_gefahren = 433
baujahr = 2005
bauart = "Cabrio"
oeffneDach(): boolean
5-2-16
Vererbung und Instanzen
• Merkregel: Vererbungsbeziehung drückt eine „ist ein“ Beziehung aus
– Beispiel: Ein PKW ist ein Fahrzeug
– Aber: Nicht jedes Fahrzeug ist ein PKW
• Variablen der Basisklasse können auf Referenzen der Subklassen verweisen
– Fahrzeug f = new Fahrzeug(); – Fahrzeug f1 = new PKW(); Fahrzeug
– Fahrzeug f2 = new Bus(); ...
– Bus b = new Bus(); Fahrzeug f3 = b; ...
• Aber nicht umgekehrt
Bus
PKW
...
...
...
...
– Bus b = new Fahrzeug(); //Fehler Security - 04 Cryptology
#17
Schlüsselwort „super“
• Jede Instanz hat eine Referenz
auf „Ober-Instanz“
Gegenstand
...
– z.B. um Attribute und Methoden
explizit zu referenzieren
– Diese heißt „super“
super
...
Fahrzeug
• Erfüllt ähnlichen Zweck zum
Zugriff auf Elemente der
Oberinstanz wie „this“ für die
aktuelle Instanz
...
...
super
• Kann nicht wie this ausgegeben
werden (zeigt auf dieselbe
Instanz)
Security - 04 Cryptology
super
Bus
PKW
...
...
...
...
#18
6
19.12.13
Aufruf des „super“-Konstruktors
• Aufruf des Konstruktors der Oberklasse
– Nur aus Konstruktor möglich
– Muss erster Aufruf im Konstruktor sein
• Syntax: super(…evtl. Parameter…) – class Fahrzeug { Fahrzeug(int i) { /* Code des Konstruktors */ } } – class Bus extends Fahrzeug { Bus() { super(1); } } Security - 04 Cryptology
#19
Aufruf des „super“-Konstruktors: Beispiel
Ruft Konstruktor von „Object“ auf
Security - 04 Cryptology
#20
Aufruf der Super-Methode
• Ruft Methode der Oberklasse auf
– Nur möglich im Konstruktor und in Methoden
• Ohne super würde die Methode der aktuellen
Klasse aufgerufen
• Syntax
– super.methodenName(…evtl. Parameter…) Security - 04 Cryptology
#21
7
19.12.13
Aufruf der Super-Methode: Beispiel
Security - 04 Cryptology
#22
Zugriff auf Super-Attribute
• Greift auf Attribut der Oberklasse zu
• Ohne super würde (falls vorhanden) das
Attribut in der aktuellen Klasse verwendet
werden
• Syntax: super.attributName = 123; Security - 04 Cryptology
#23
Zugriff auf Super-Attribute: Beispiel
Security - 04 Cryptology
#24
8
19.12.13
Modifier
Modifier
• Wichtig bei Objektorientierung: „information hiding“
– Jeder soll nur das verwenden können, was relevant ist
– Trägt zur Übersichtlichkeit und Fehlersicherheit bei
• Zugriffsbeschränkung wird über sog. Modifier gesteuert
– Schlüsselwörter: public, protected, private, „nichts“
• Möglich für
–
–
–
–
Klassen
Attribute
Konstruktoren
Methoden
Klasse Obst
• Attribute
– Gewicht
• double gewichtInKg;
• Methoden
– double getGewichtInKg(); • Gibt Gewicht dieser Obstinstanz zurück
9
19.12.13
package de.uzl.itm.prog.modifierbsp;
public class Obst {
Beispiel: Klasse Obst
private double gewichtInKg;
public Obst(double gewichtInKg) {
this.gewichtInKg = gewichtInKg;
}
Private Attribute:
Nur aus Klasse
zugreifbar
public double getGewichtInKg() {
return gewichtInKg;
}
}
Öffentlicher
Konstruktor und
Methode: Von
überall aus
aufrufbar
Obst obst1 = new Obst(0.346);
obst1.gewichtInKg = 0.752;
obst1.getGewichtInKg();
Beispiel: Klasse Obst
Ok, da
öffentlicher
Konstruktor
Nicht möglich,
da das Attribut
privat ist
Ok, da
Methode
öffentlich ist
Modifier
Zugriff möglich von …
Klasse Package
Modifier
public
protected*
Keine Angabe:
„package private“
private*
þ
þ
þ
þ
þ
þ
þ **
ý
Unterklasse
þ
þ
ý **
ý
Überall
þ
ý
ý
ý
*) Nicht für Klassen (nur für Attribute, Konstruktoren und Methoden)
**) Je nachdem ob Unterklasse im selben Package oder nicht
10
19.12.13
Klasse Apfel
• Attribute
– Preis pro kg
• double preisProKg; • Methoden
– Apfel(double gewichtInKg, double preisProKg) • Konstruktor mit gewichtInKg und preisProKg
• Initialisiert die Attribute
– double getPreisInEuro(); • Berechnet Preis basierend auf Gewicht und Gewicht pro kg
package de.uzl.itm.prog.modifierbsp;
public class Apfel extends Obst {
Beispiel: Klasse Apfel
private double preisProKg;
public Apfel(double gewichtInKg,
double preisProKg) {
super(gewichtInKg);
this.preisProKg = preisProKg;
}
public double getPreis() {
return gewichtInKg * preisProKg;
}
}
Problem:
Zugriff auf
privates Attribut
der Oberklasse
nicht möglich
package de.uzl.itm.prog.modifierbsp;
public class Obst {
Beispiel: Klasse Obst
protected double gewichtInKg;
public Obst(double gewichtInKg) {
this.gewichtInKg = gewichtInKg;
}
Lösung:
Zugriff für
Unterklassen
erlauben
public double getGewichtInKg() {
return gewichtInKg;
}
}
11
19.12.13
package de.uzl.itm.prog.modifierbsp;
public class Obst {
Beispiel: Klasse Obst
protected double gewichtInKg;
public Obst(double gewichtInKg) {
this.gewichtInKg = gewichtInKg;
}
Alternative:
„package private“
erlaubt Zugriff im
selben Package
public double getGewichtInKg() {
return gewichtInKg;
}
}
Beispiel: Klasse Obst
Obst obst1 = new Obst(0.346);
obst1.gewichtInKg = 0.752;
obst1.getGewichtInKg();
Achtung!,
Zugriff jetzt
möglich, da
Klasse Main im
selben
Package
Polymorphismus
12
19.12.13
Polymorphismus
• Methoden von Oberklassen können in Unterklassen
redefiniert werden
• Überladen (Overloading)
– Methode mit gleichem Namen und unterschiedlichen
Parametern
– Rückgabetyp bleibt gleich
• Überschreiben (Overriding) à Polymorphismus
– Gleiche Signatur einer Methode in einer Unterklasse
– Nach außen gleiches Interface, aber anderes Verhalten
Überladen (altes Beispiel)
• Gleicher Methodenname und Rückgabetype, andere Parameterliste
– void gebeAus(int i); – void gebeAus(String s); – void gebeAus(double d); • Verwendung
– gebeAus(1);
//Aufruf von void gebeAus(int i); – gebeAus(“Hallo“);
//Aufruf von void gebeAus(String s); – gebeAus(2.098); //Aufruf von void gebeAus(double d); • Wesentliches Prinzip: Aufruf der „passenden“ Methode basierend auf
den Typen der übergebenen Parameter
Security - 04 Cryptology
#38
Überschreiben
Beispiel:
Was passiert?
• class Fahrzeug { • Welche Methode wird
void motorAn() {...} aufgerufen?
} • Die aus Fahrzeug oder die
• class PKW extends aus PKW?
Fahrzeug { void motorAn() {...} • Anders gefragt: Was ist
} relevant?
• Fahrzeug f = new PKW(); f.motorAn(); – Der Typ der Referenz f?
– Der Typ der Instanz, die f
referenziert?
Security - 04 Cryptology
#39
13
19.12.13
Überschriebene Methoden
• In Java entscheidet immer der Typ der referenzierten Instanz
• Fahrzeug f = new Fahrzeug(); f.motorAn(); – Methode aus Klasse Fahrzeug
• Fahrzeug f = new PKW(); f.motorAn(); – Methode aus Klasse PKW
• Fahrzeug f = new Bus(); f.motorAn(); – Methode aus Klasse Bus
Security - 04 Cryptology
#40
Polymorphismus: Beispiel
• Implementierung eines Obstkorbs
– Menge von Früchten „speichern“
– Preisberechnung (Gesamtpreis)
Benötigte Klassen
• Obst (Oberklasse)
– Wir wollen „Obst“ in den Obstkorb tun
• Apfel (Unterklasse von Obst)
• Birne (Unterklasse von Obst)
• Obstkorb
– Speichert Instanzen von Obst
14
19.12.13
Klasse Obst
• Methode gibt Fehler (-1) zurück
– Das abstrakte Konzept Obst kostet ja nichts
Public,
damit sie
„von
außen“
aufgerufen
werden
kann
Security - 04 Cryptology
#43
package de.uzl.itm.prog.modifierbsp;
public class Apfel extends Obst {
Beispiel: Klasse Apfel
private double preisProKg;
public Apfel(double gewichtInKg,
double preisProKg) {
super(gewichtInKg);
this.preisProKg = preisProKg;
}
Überschriebene
Methode
public double getPreis() {
return gewichtInKg * preisProKg;
}
}
Klasse Birne
• Attribute
– Preis pro kg
• double preisProKg; • Methoden
– Birne(double gewichtInKg, double preisProKg) • Konstruktor mit gewichtInKg und preisProKg
• Initialisiert die Attribute
– double getPreisInEuro(); • Berechnet Preis basierend auf Gewicht und Gewicht pro kg
15
19.12.13
package de.uzl.itm.prog.modifierbsp;
public class Apfel extends Obst {
Beispiel: Klasse Birne
private double preisProKg;
public Apfel(double gewichtInKg,
double preisProKg) {
super(gewichtInKg);
this.preisProKg = preisProKg;
}
public double getPreis() {
return gewichtInKg * preisProKg;
}
Überschriebene
Methode
}
Klasse Obstkorb
• Attribute
– Speichert max. 10 Instanzen vom Typ Obst
(mehr Platz ist nicht)
– Hat Array vom Typ Obst:
Obst obst[] = new Obst[10]; • Methoden
– boolean legeInKorb(Obst o); • Legt eine Obst-Instanz in den Korb
– double getGesamtPreis(); • Berechnet Gesamtpreis des enthaltenen Obsts
Klasse Obstkorb
• Kann 10 Instanzen von
„Obst“ speichern
– Damit auch Apfel und
Birne
• Berechnet Gesamtpreis
– Ruft dazu die Methode
getPreis() aller ObstInstanzen auf
– Durch Polymorphie wird
die Methode der
jeweiligen Instanz
aufgerufen, auf die
verwiesen wird
Security - 04 Cryptology
#48
16
19.12.13
Eine Klasse mit Main-Methode zum Testen
• Erzeugt
– Eine Instanz von
Obstkorb
– Ein paar Instanzen
von Apfel und Birne
• Legt die ObstInstanzen in den
Obstkorb
• Gibt den
Gesamtpreis aus
Mehr Früchtchen
• Ergänzung des
Warensortiments
• Kiwi als neue Frucht
• Preis nicht pro kg
sondern pro Stück
Klasse Kiwi
• Attribute
– Preis pro Stück
• double preisProStueck;
• Methoden
– double getPreisInEuro(); – Kiwi(double preisProStueck); 17
19.12.13
Klasse Kiwi
Security - 04 Cryptology
#52
Zusammenfassung
•
Über Vererbung können gemeinsame Attribute, Methode, etc. ähnlicher
Klassen zusammengefasst werden
– Unterklassen erben alle Eigenschaften der Oberklasse
– In Java kann man von einer Oberklasse erben
– Mit super kann man auf die Oberklasse zugreifen (Methoden, Attribute, Konstruktoren)
– In Java ist ein Objekt ohne explizite Angabe der Oberklasse implizit von Object abgeleitet
•
Modifier: Zugriff auf Attribute, Methoden und Konstruktoren regeln
•
Polymorphie: andere Klassen kennen nur gemeinsame Oberklasse
– Das Verhalten wird durch die konkrete referenzierte Instanz bestimmt
– Es werden immer die Methoden der referenzierten Instanz aufgerufen
– Wird durch Überschreiben von Methoden in Unterklassen erreicht
Security - 04 Cryptology
#53
18