Interfaces - Universität zu Lübeck

Werbung
Programmierkurs Java
Abstrakte Klassen und Methoden
& Interfaces
Prof. Dr. Stefan Fischer
Institut für Telematik, Universität zu Lübeck
http://www.itm.uni-luebeck.de/people/fischer
Vererbungshierarchie
Obst
double getPreisInEuro();
Apfel
Birne
Kiwi
double getPreisInEuro();
double getPreisInEuro();
double getPreisInEuro();
#2
Problem dieser Lösung
• Methode „double getPreisInEuro();“
– In den Klassen Apfel, Birne und Kiwi implementiert
– Aber auch in der Klasse Obst
• Welchen Sinn hat die Implementierung in Obst?
#3
Oberklasse Obst: getPreisInEuro()
• Bisherige Implementierung komplett sinnlos
– Die Methode wird sowieso in den Unterklassen überschrieben
– Macht sogar Probleme, wenn man Instanzen von Obst
verwendet (Negativer Preis)
• Eigentlich brauchen wir die Klasse nur, damit wir die
Methode double getPreisInEuro() in Obst haben
#4
Weiteres Problem dieser Lösung
• Wer erzwingt eigentlich, dass man in Unterklassen
die Methode getPreisInEuro() überschreibt?
• Der Compiler tut es nicht (siehe Beispiel unten)
– Erstellt man eine Instanz von Apfel, wird die Methode
aus Obst aufgerufen
– Die Methode wurde ja nicht überschrieben
#5
Lösung: Abstrakte Klassen und Methoden
• Man kann Klassen und Methoden als abstrakt
kennzeichnen
• Bedeutung: Von abstrakten Klassen können
keine Instanzen erzeugt werden
• Ist mindestens eine Methode einer Klasse
abstrakt, so ist auch die Klasse abstrakt
#6
Beispiel: Abstrakte Klasse „Obst“
• Abstrakte Klassen: Keyword abstract
– Syntax: abstract class XXX {...}
• Beispiel:
#7
Beispiel: Abstrakte Klasse „Obst“
• Von abstrakten Klassen können keine Instanzen erzeugt
werden
• Löst das erste der beiden Probleme
– Erzeugen von Instanzen wird vom Compiler verhindert
#8
Erzwingen der Implementierung von Methoden
• Wie kann man nun erzwingen, dass in Unterklassen bestimmte
Methoden implementiert werden?
• Lösung: durch abstrakte Methoden
– public abstract double getPreisInEuro();
– Nur Signatur (wg. ; am Ende) aber keine Implementierung
• Enthält eine Klasse mindestens eine abstrakte Methode, so
muss die Klasse auch abstrakt sein
– D.h. es muss abstract class Obst heißen
– Existenz mindestens einer abstrakten Methode: es können von dieser
Klasse auch keine Instanzen erzeugt werden
#9
Beispiel: Abstrakte Methode in Obst
• Obst enthält nun eine abstrakte Methode
– Die Signatur der Methode ist für alle Unterklassen
definiert
• Signatur reicht aus, um Methode aufzurufen
– Wie sie intern funktioniert, ist egal
#10
Beispiel: Abstrakte Methode in Obst
• Unterklassen erben die abstrakte Methode
– Daher: Compilerfehler
• Unterklasse soll nicht abstrakt sein:
– Sie muss alle abstrakten Methoden implementieren
#11
Abstract und Vererbung
• Abstrakte Methoden werden
vererbt
• Damit eine Klasse instanziiert
werden kann (also nicht abstrakt
ist), müssen in der
Vererbungshierarchie alle
abstrakten Methoden mit
Implementierungen
überschrieben werden
• Wo dies geschieht ist dabei egal
#12
Abstract und die Früchte
•
Klassen Apfel, Birne und
Kiwi sind nicht abstrakt
– Können dies nur sein, weil
sie die abstrakte Methode
aus Obst implementieren
•
Darüber kann man
erzwingen, dass
Programmierer bestimmte
Methoden implementieren
– Damit realisiert man eine
Schnittstelle
– Auch API (Application
Programming Interface)
genannt
#13
Abstract und nicht-abstract mischen
• Nicht abstrakte Methoden können abstrakte Methoden verwenden
– Möglich, da bei nicht-abstrakten Instanzen von Unterklassen die
Methode ja implementiert sein muss
– Damit können bestimmte Elemente der Implementierung offen
gelassen werden
• Vorteil: Verhalten, das bei allen Unterklassen sehr ähnlich ist, kann in
die Oberklasse verschoben werden
#14
Beispiel
• Beide Klassen implementieren
die Methode getName
unterschiedlich
• Methode tueWasMit(GutenTag
g) in der Klassen Main kennt nur
das Interface von „GutenTag“
• Kann damit getName() oder
stellDichVor() aufrufen
– stellDichVor() ruft getName der
jeweiligen Instanz auf
#15
Interfaces
Interfaces
• Können Klassen auch von mehreren Oberklassen erben?
– Sogenannte Mehrfachvererbung
– Prinzipiell ja (z.B. in C++), in Java jedoch nicht
– Es können Konflikte entstehen, deren Auflösung kompliziert sein kann
• Java bietet ähnliche Funktionalität über einen Trick
– Neben „echten“ Oberklassen gibt es sog. Interfaces
• Ein Interface enthält lediglich Methodensignaturen
– D.h. keine Methodenimplementierung / kein Code
– Vergleichbar mit Klassen, die nur abstrakte Methoden enthalten
#17
Abstrakte Klasse vs. Interface
• Abstrakte Klasse
• abstract class Obst {
public abstract double getPreisInEuro();
}
• Interface
• interface Obst {
double getPreisInEuro();
}
• Abstract wird implizit für Klasse und Methoden angenommen
und muss daher nicht explizit auftauchen
• Methoden eines Interfaces sind immer public
#18
Abstrakte Klasse vs. Interface
• Abstrakte Klassen können auch „normale“ Methoden
enthalten (mit Implementierung)
– abstract class Obst {
public void gebeAus() { ... }  OK
public abstract double getPreisInEuro();
}
• Bei Interfaces ist dies nicht erlaubt
– interface Obst {
void gebeAus() { ... }  nicht möglich
double getPreisInEuro();
}
#19
Implementieren von Interfaces
• Von einem Interface wird nicht geerbt, sondern es wird
implementiert
– Schlüsselwort: implements
• Eine Klasse kann von max. einer Klasse erben
– Aber sie kann beliebig viele Interfaces implementieren
– Wenn mehrere Klassen ein Interface implementieren,
besitzen sie Methoden mit identischen Signaturen
• Beispiel: siehe nächste Folie
#20
Interfaces: Beispiel
• class PKW extends Fahrzeug
implements Gebrauchsgegenstand, CoolesMaennerspielzeug
{
//alle Interface-Methoden müssen implementiert werden
}
• Ein PKW „ist-ein“ Fahrzeug, GebrauchsGegenstand und
CoolesMaennerspielzeug
Fahrzeug
Gebrauchs
Gegenstand
CoolesMaenner
spielzeug
PKW
#21
Interfaces: Obstbeispiel
• Bei manchen Obstsorten ist Herkunftsland
wichtig
– Methode „String getHerkunftsland();“
– Soll (wenn bekannt) von Obstsorten implementiert
werden
• Beispiel Kiwi
– Klasse Kiwi erbt schon von Obst
– Kann daher keine weitere Klasse „extenden“
#22
Interfaces: Obstbeispiel
• Daher: Neues Interface „Herkunftsland “
– public interface Herkunftsland {
String getHerkunftsland();
}
• Klasse Kiwi implementiert das Interface
– class Kiwi extends Obst implements Herkunftsland {
String getHerkunftsland() {
return “Neuseeland“;
}
}
#23
Vererbungshierarchie
•
Kiwi „ist-ein“
– Obst
– Herkunftsland
Obst
•
Instanzen vom Typ Kiwi können per
Typecast auf Obst und Herkunftsland
abgebildet werden
•
Beispiel
Herkunftsland
Kiwi
– Obst obst = new Kiwi();
– Herkunftsland land = new Kiwi();
– Obst obst2 = (Obst) land;
– Herkunftsland land2 = (Herkunftsland) obst;
#24
Beispiel: instanceof
•
Obst o = new Obst();
–
•
a instanceof Obst
a instanceof Apfel
a instanceof Herkunftsland
Obst k = new Kiwi();
–
–
–
–
•
 true
Apfel a = new Apfel();
–
–
–
•
o instanceof Obst
k
k
k
k
instanceof
instanceof
instanceof
instanceof
Obst
Herkuntsland
Kiwi
Apfel
 true
 true
 false
// ok, da: Kiwi ist ein Obst (upcast)
 true
 true
 true
 false
Obstkorb korb = new Obstkorb();
–
–
korb instanceof Obst
korb instanceof Obstkorb
 false
 true
#25
Zusammenfassung
•
Attribut „abstract“ an Klassen verhindert deren Instanziierung
•
Abstrakte Methoden
– Machen die gesamte Klasse abstrakt
– Erzwingen, dass in Unterklassen diese Methode implementiert werden muss, damit diese
nicht mehr abstrakt sein müssen
– Resultat: Gemeinsame Schnittstelle bzw. Interface
•
Interfaces
– Interfaces sind wie abstrakte Klassen mit ausschließlich abstrakten Methoden
– In Java kann eine Klasse nur von einer Oberklasse erben aber von beliebig vielen
Interfaces
– Ein Interface implementiert man, von Oberklassen erbt man
#26
Herunterladen