The problem
If class D inherits from both B and C, and both inherit a method show() from A and override it differently, then D does not know which show() to use. This is the diamond problem. Java avoids it by allowing a class to extend only one class but implement many interfaces.
interface Flyable { void fly(); }
interface Swimmable { void swim(); }
class Duck extends Animal implements Flyable, Swimmable {
Duck(String name) { super(name); }
public void fly() { System.out.println(name + " flies"); }
public void swim() { System.out.println(name + " swims"); }
}How the Duck example avoids the problem
Duck extends only one class, Animal, so it inherits code (the name attribute and the constructor) from exactly one place. From the two interfaces it inherits only promises: Flyable promises a fly() method and Swimmable promises a swim() method. Duck writes the bodies itself, so there is never any doubt about which code runs. A Duck can be used wherever an Animal, a Flyable or a Swimmable is expected:
Duck d = new Duck("Donald");
Flyable f = d; // a Duck is Flyable
Swimmable s = d; // and Swimmable
f.fly(); // Donald flies
s.swim(); // Donald swimsWhat if two interfaces have the same default method?
Since Java 8, interfaces can contain default methods, with a body. If a class implements two interfaces that both supply the same default method, the diamond problem could come back. Java refuses to guess: the class must override the method, and can choose a version with InterfaceName.super.method():
interface Camera { default String info() { return "Camera"; } }
interface Phone { default String info() { return "Phone"; } }
class SmartPhone implements Camera, Phone {
@Override
public String info() {
return Phone.super.info() + " with " + Camera.super.info();
}
}
// new SmartPhone().info() returns "Phone with Camera"How other languages handle it
- C++ allows a class to have several parent classes. The programmer must resolve clashes by naming the parent (
B::show()), and uses virtual inheritance to keep only one copy of the shared grandparent A. - Python allows multiple inheritance and uses a fixed rule, the method resolution order (MRO), which searches the parents from left to right.
- Java and C# allow only single inheritance of classes, plus any number of interfaces. This rule is simpler and safer.
Remember
- The diamond problem: two parents provide different versions of the same method, and it is unclear which one the child inherits.
- Java: extend one class, implement many interfaces.
- If two interfaces provide the same default method, the class must override it.