The "diamond problem" (sometimes referred to as the "deadly diamond of death") is an ambiguity that arises when two classes B and C inherit from A, and class D inherits from both B and C. If there is a method in A that B and C have overridden, and D does not override it, then which version of the method does D inherit: that of B, or that of C?
For example, in the context of GUI software development, a class Button may inherit from both classes Rectangle (for appearance) and Clickable (for functionality/input handling), and classes Rectangle and Clickable both inherit from the Object class. Now if the equals method is called for a Button object and there is no such method in the Button class but there is an overridden equals method in Rectangle or Clickable (or both), which method should be eventually called?
It is called the "diamond problem" because of the shape of the class inheritance diagram in this situation. In this case, class A is at the top, both B and C separately beneath it, and D joins the two together at the bottom to form a diamond shape.
It is called the "diamond problem" because of the shape of the class inheritance diagram in this situation. In this case, class A is at the top, both B and C separately beneath it, and D joins the two together at the bottom to form a diamond shape.
Java 8 introduces default methods on interfaces. If
A,B,C are interfaces, B,C can each provide a different implementation to an abstract method of A, causing the diamond problem. Either class D must re-implement the method (the body of which can simply forward the call to one of the super implementations), or the ambiguity will be rejected as a compile error. Prior to Java 8, Java was not subject to the Diamond problem risk, as Java does not support multiple inheritance.Java Solution : We can resolve this issue by using a qualified name as we can understand by the below example.
The sample code in the answer by Óscar López is excellent. Here's another example:class Base {
int x = 10;
}
interface Interface {
int x = 20;
}
class SingleInheritance implements Interface {
int y = 2 * x; // ok
}
class MultipleInheritance extends Base implements Interface {
int y = 2 * x; // compile-time error
int z = 2 * Interface.x; // ok
}
void aMethod(MultipleInheritance arg) {
System.out.println("arg.x = " + arg.x); // compile-time error
System.out.println("x = " + Interface.x); // ok
} Java Itself provided a solution to the above problem as follows:In Java 8, an interface now can declare both default methods and static method implementations. This brings a large chunk of the Diamond of Death problem into the language.
Java 8 has introduced the concept of default methods which allow the interfaces to have methods with implementation without affecting the classes that implement the interface.
// A simple program to Test Interface default methods in javainterface TestInterface{ //abstract method public void square(int a); //default method default void show() { System.out.println("Default Method Executed"); }}class TestClass implements TestInterface{ //implementation of square abstract method public void square(int a) { System.out.println(a*a); } public static void main(String args[]){ TestClass d = new TestClass(); d.square(4); //default method executed d.show(); }} |
16The default methods were introduced to provide backward comparability so that existing interfaces can use the lambda expressions without implementing the methods in the implementation class. Default methods are also known as defender methods or virtual extension methods.
Default Method Executed
Default Methods and Multiple Inheritance:
In case both the implemented interfaces contain default methods with same method signature, the implementing class should explicitly specify which default method is to be used or it should override the default method.// A simple Java program to demonstrate multiple inheritance through default methods.interface TestInterface1{// default method default void show() { System.out.println("Default TestInterface1"); }}interface TestInterface2{// Default method default void show() { System.out.println("Default TestInterface2"); }}// Implementation class codeclass TestClass implements TestInterface1, TestInterface2{ // Overriding default show method public void show(){ // use super keyword to call the show // method of TestInterface1 interface TestInterface1.super.show(); // use super keyword to call the show // method of TestInterface2 interface TestInterface2.super.show(); } public static void main(String args[]){ TestClass d = new TestClass(); d.show(); }} |
Default TestInterface1Important Points:
Default TestInterface2
- Interfaces can have default methods with implementation from java 8 onwards.
- Interfaces can have static methods as well similar to static method of classes.
- Default methods were introduced to provide backward comparability for old interfaces so that they can have new methods without effecting existing code.
- http://www.geeksforgeeks.org/default-methods-java/
- https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem
- https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html
- https://stackoverflow.com/questions/9860811/do-interfaces-solve-the-deadly-diamond-of-death-issue
Comments
Post a Comment