Default-Implementierungen in verschiedenen Interfaces
Eine Klasse kann nur von einer Basisklasse erben, aber sie kann mehrere Interfaces implementieren. Einer Klasse können damit unterschiedliche Implementierungen der gleichen Default-Methode zur Verfügung stehen. Diese Situation ähnelt auf den ersten Blick der Mehrfachvererbung, die es in Java aus guten Gründen nicht gibt.
Mehrfache Default-Methoden
Der Compiler sammelt beim Übersetzen einer Klasse zunächst alle infrage kommenden Default-Methoden in allen direkt oder indirekt implementierten Interfaces ein. Aus dieser Menge streicht er Kandidaten, die von anderen Kandidaten redefiniert werden. Es bleiben also nur die am weitesten abgeleiteten Default-Methoden erhalten. Am Ende muss genau ein Kandidat übrig bleiben. Andernfalls bricht der Compiler mit der gezeigten Fehlermeldung ab.
Die folgende Typhierarchie illustriert dieses Vorgehen:
Das Interface Machine repräsentiert eine beliebige Maschine.
Abgeleitet von Machine ist das Interface Robot für autonome Systeme.
WalkingRobot und FlyingRobot sind Roboter mit unterschiedlichen Bewegungsmöglichkeiten.
TinCan kann sowohl laufen als auch fliegen und implementiert deshalb die beiden Interfaces WalkingRobot und FlyingRobot.
Die folgenden Definitionen setzen diese Konstruktion um.
interface Machine { void talk() default { throw new RuntimeException("I won\'t talk to you"); } }
class TinCan implements WalkingRobot, FlyingRobot { public static void main(String... args) { Machine tinCan = new TinCan(); tinCan.move(); } }
DiamondProblem.java: Sich widersprechende Default-Methoden in zwei verschiedenen Interfaces.
Jetzt stößt der Compiler auf kollidierende Implementierungen und bricht mit einem Fehler ab:
$ javac TinCan.java TinCan.java: error: class TinCan inherits unrelated defaults for move() from types WalkingRobot and RollingRobot
Das Problem verschwindet, wenn
entweder eine der walk-Methoden in WalkingRobot und FlyingRobot gelöscht wird oder
TinCan selbst eine walk-Methode definiert.
Diamond-Problem der Mehrfachvererbung
Das hier dargestellte Problem ist auch als Diamond-Problem der Mehrfachvererbung bekannt. Dieses Problem kann bei größeren Typhierarchien schwer überschaubare Konsequenzen haben, insbesondere wenn ein Teil der beteiligten Typen nur in übersetzter Form vorliegt und der Quelltext fehlt. Verschiedene Programmiersprachen gehen unterschiedlich damit um. Die Regelung von Java ist verhältnismäßig geradlinig.
Die Umsetzung in Java profitiert davon, dass Default-Methoden keine Daten mit sich bringen, sondern nur Funktionalität (siehe Seite ▶). Zum Beispiel stellt sich daher die Frage nicht, wie oft ein Interface mit Default-Methoden auf unterschiedlichen Wegen „ererbt” wird. Infolgedessen ist auch das Problem einer Reihenfolge oder Rangordnung gegenstandslos.