Programmieren mit Java IIhttp://sol.cs.hm.edu/4129Inhaltsverzeichnis
5. Geschachtelte Klassen5.6 Default-Methoden (Java 8) 5.6.4 Vererbung und Default-Methoden
Konkurrierende Default-Methoden
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: image/svg+xml Machine +talk: «Interface» Robot +talk: «Interface» FlyingRobot «Interface» WalkingRobot «Interface» TinCan +main(String[]): Die folgenden Definitionen setzen diese Konstruktion um.
interface Machine {

void talk() default {

throw new RuntimeException("I won\'t talk to you");

}

}



interface Robot extends Machine {

void talk() default {

System.out.println("\"Blah\"");

}

}



interface WalkingRobot extends Robot {

}



interface FlyingRobot extends Robot {

}



class TinCan implements WalkingRobot, FlyingRobot {

public static void main(String... args) {

Machine tinCan = new TinCan();

tinCan.talk();

}

}

DiamondNoProblem.java: Eindeutige Default-Methode bei verschiedenen Interfaces.
Der Compiler übersetzt diesen Quelltext klaglos, weil er eine eindeutige Default-Methode findet. Das Programm ruft die talk-Methode von Robot auf:
$ java TinCan

"Blah"
Kollidierende Default-Methoden
Das Bild ändert sich mit Default-Methoden in den beiden Interfaces WalkingRobot und FlyingRobot: image/svg+xml Machine «Interface» Robot +move: «Interface» FlyingRobot «Interface» WalkingRobot «Interface» TinCan +move: +move: +main(String[]):
interface Machine {

void move();

}



interface Robot extends Machine {

}



interface FlyingRobot extends Robot {

void move() default {

System.out.println("Flap-flap ...");

}

}



interface WalkingRobot extends Robot {

void move() default {

System.out.println("Hop, hop, ...");

}

}



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
  1. entweder eine der walk-Methoden in WalkingRobot und FlyingRobot gelöscht wird oder
  2. 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.