So wie zwar eine Sonnenfinsternis selten ist, aber vorkommt, so kann auch die seltene Konstellation eintreten, dass eine Klasse von zwei Seiten eine Implementierung bekommt. Erbt zum Beispiel eine Klasse A eine Implementierung für eine Methode f() und implementiert die Klasse A gleichzeitig eine erweiterte Schnittstelle I, von der sie eine Default-Methode f() vorgeschlagen bekommt, ist vom Compiler bzw. der Laufzeitumgebung eine Entscheidung gefragt. Zunächst muss der Compiler entscheiden, ob so etwas überhaupt syntaktisch korrekt ist. Die Antwort lautet: ja.
Ein Beispiel soll denn Fall demonstrieren:
interface Buyable {
double price();
default boolean hasPrice() { return price() > 0; }
}
abstract class NotBuyable implements Buyable {
@Override public boolean hasPrice() { return false; }
}
public class Love extends NotBuyable implements Buyable {
@Override public double price() { return 10_01; }
public static void main(String[] args) {
System.out.println( new Love().hasPrice() ); // false
}
}
Wieder ist Buyable eine Schnittstelle mit einer Default-Methode hasPrice(). Neu ist eine abstrakte Klasse NotBuyable, die hasPrice() mit false beantwortet. Eine Klasse Love erweitert erstens NotBuyable und bekommt von dort hasPrice() und implementiert zweitens Buyable, was ebenfalls eine Implementierung über die Default-Methode hasPrice() mitbringt. Nachdem wir festgestellt haben, dass dieses Szenario syntaktisch korrekt ist, muss die Laufzeitumgebung eine Entscheidung fällen. Die sieht so aus, dass die Implementierung aus einer Klasse gewinnt. Ausgabe ist also false.
Bleibt abschließend die Frage, wie sich der Compiler verhält, wenn einer Klasse aus zwei erweiterten Schnittstellen eine Default-Methode angeboten wird. Kurz und knapp: Das führt zu einem Compilerfehler. Die Klasse RockAndRoll zeigt dieses Dilemma:
interface Buyable {
boolean hasPrice();
}
interface Love extends Buyable {
@Override default public boolean hasPrice() { return false; }
}
interface Guitar extends Buyable {
@Override default public boolean hasPrice() { return false; }
}
public class RockAndRoll implements Love, Guitar { } // Compilerfehler
Ähnliche Beiträge
- Default-Methoden aus speziellen Oberschnittstellen ansprechen
- Abstrakte überschriebe Schnittellenoperationen nehmen Default-Methoden weg
- Nachträgliches Implementieren von Schnittstellen
- Default-Methoden, Teil 1, Update mit aktueller Java 8 Syntax
- Statische ausprogrammierte Methoden in Schnittstellen