Motivation
|
Die Trennung von Schnittstelle und Implementierung
kann mit Hilfe von Vererbung und abstakten und konkreten Klassen
realisiert werden.
|
| |
Beispiel
|
abstract class Stack {
abstract Stack push(int i);
abstract boolean isEmpty();
...
}
class MyStack extends Stack {
Stack push(int i) { return ...; }
boolean isEmpty() { return ...; }
...
}
class YourStack extends Stack {
Stack push(int i) { return ...; }
boolean isEmpty() { return ...; }
...
}
|
| |
|
Problem:
Ein Objekt kann möglicherweise viele Schnittstellen unterstützen.
|
Beispiel
|
abstract class Size {
abstract int size();
}
class MyStack extends Stack, Size {
Stack push(int i) { return ...; }
boolean isEmpty() { return ...; }
...
int size() { return ...; }
}
|
| |
|
Mehrfachvererbung wird erforderlich!
|
| |
|
Richtig aber nicht gebräuchlich: Mehrfachbeerbung.
|
|
Mehrfachbeerbung von Klassen mit Datenfeldern
ist semantisch und implementierungstechnisch nicht einfach zu lösen.
|
| |
|
Mehrfachbeerbung von Klassen mit unterschiedlich
implementierten Methoden mit gleicher Signatur
ist semantisch und implementierungstechnisch nicht einfach zu lösen.
|
| |
|
Besitzt eine beerbte Klasse weder Datenfelder noch Methodenrümpfe,
so entfällt die Problematik bei der Mehrfachbeererbung.
|
| |
Lösung
|
in Java
|
Schnittstellen
|
interfaces
|
|
sind einfache abstrakte Klassen ohne Datenfelder und ohne Methodenrümpfe
|
| |
|
Mehrfachvererbung mit Schnittstellen ist in Java möglich.
|
Beispiel
|
interface I {
void f();
}
interface J {
void g();
}
class X implements I, J {
void f() { ... }
void g() { ... }
}
|
| |
|
Schnittstellen werden mit implements beerbt.
|
|
Es kann eine Liste von Schnittstellen angegeben werden.
|
|
Die Reihenfolge ist nicht relevant.
|
|
Sollten in zwei Schnittstellen gleiche Methoden deklariert sein, führt dieses
weder zu Verständnis- noch zu Implementierungsproblemen.
|
|
Neben beliebig vielen Schnittstellen kann genau eine Klasse beerbt werden.
|
|
|
| |
Redesign
|
für das Stack-Beispiel
|
Schnittstelle
|
interface Stack {
boolean isEmpty();
Stack push(int i);
Stack pop();
int top();
boolean preTop();
boolean prePop();
}
|
| |
weitere Schnitstelle |
interface Size {
int size();
}
|
| |
Default- Implementierungen
|
abstract class AbstractStack
implements Stack {
boolean preTop() { ... }
boolean prePop() { ... }
}
|
| |
Konkrete Implementierung
|
class MyStack
extends AbstractStack
implements Size {
boolean isEmpty() { ... }
Stack push(int i) { ... }
Stack pop() { ... }
int top() { ... }
int size() { ... }
}
|
| |
Referenzen |
Schnittstellen bilden Datentypen, wie Klassen und Felder.
Referenzen auf Schnittstellen sind möglich.
|
| |
Beispiel |
Stack s1 = new MyStack();
Size s2 = new MyStack();
... s1.push(42) ...
... s2.size() ...
|
| |
|
Schnittstellen (interfaces) sind per Definition öffentlich sichtbar (public).
|
|
Alle Methodendeklarationen in Schnittstellen sind per Definition
öffentlich sichtbar (public).
|