Monday, 21 August 2017

Default Methods in Interface, Multiple Inheritance and Diamond Problem in Java 8

Ever since Java 8 introduced default and static methods in JDK 8, it's become possible to define non-abstract methods in interfaces and since in Java one class can implement multiple interfaces and because there can be concrete methods in interfaces, the diamond problem surfaced again. What will happen if two interface has methods o the same name and a Java class inherit from it? Many Java programmer also asks me the question that, is Java 8 is also supporting multiple inheritances of classes, as it seems because interface with methods is similar to abstract class or in that any class. Well, it’s not.

Multiple inheritances of classes is not supported in Java 8, instead compiler will do additional checks to avoid ambiguity in calling default methods and Diamond problem, which could come if a class implements two interface which contains same default methods as shown in the following example, it will not compile in Java 8, because of ambiguity in calling default method write() from a class, which extends both Poet and Writer interface.

interface Poet {
    default void write() {
        System.out.println("Poet's default method");
    }
}

interface Writer {
    default void write() {
        System.out.println("Writer's default method");
    }
}

public class Multitalented implements Poet, Writer{
 
    public static void main(String args[]){
        Multitalented john = new Multitalented();
        john.write();  // which write method to call, from Poet
                       // or, from Writer
    }
}

Output:
Compile Time Error : class Multitalented inherits unrelated defaults for write() from types Poet and Writer

In order to solve this error, you need to override the write() method in your implementation class i.e. class Multitalented here, this will remove the ambiguity, making the compiler happy enough to compile this class.

public class Multitalented implements Poet, Writer{
   
    @Override
    public void write(){
        System.out.println("Writing stories now days");
    }
   
    public static void main(String args[]){
        Multitalented john = new Multitalented();
        john.write();  // This will call Multitalented#write() method
    }
}

Output:
Writing stories now days

So until you don't create ambiguity by using default methods on interfaces, you are fine to use it. If it creates ambiguity, the compiler will alert you by throwing compile time error "inherits unrelated defaults".