Implementing two interfaces with two default methods of the same signature in Java 8

30,281

Solution 1

This is a compile-time error. You cannot have two implementation from two interfaces.

However, it is correct, if you implement the getGreeting method in C1:

public class C1 implements I1, I2 // this will compile, bacause we have overridden getGreeting()
{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }

    @Override public String getGreeting()
    {
        return "Good Evening!";
    }
}

I just want to add that even if the method in I1 is abstract, and default in I2, you cannot implement both of them. So this is also a compile-time error:

public interface I1
{
    String getGreeting();
}

public interface I2
{
    default String getGreeting() {
        return "Good afternoon!";
    }
}

public class C1 implements I1, I2 // won't compile
{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }
}

Solution 2

This is not specific to the question. But, I still think that it adds some value to the context. As an addition to @toni77's answer, I would like to add that the default method can be invoked from an implementing class as shown below. In the below code, the default method getGreeting() from interface I1 is invoked from an overridden method:

public interface I1 {
     default String getGreeting() {
        return "Good Morning!";
     }
}

public interface I2 {
    default String getGreeting() {
        return "Good Night!";
    }
}

public class C1 implements I1, I2 {       
    @Override
    public String getGreeting() {
        return I1.super.getGreeting();
    }
}

Solution 3

If a class implements 2 interfaces both of which have a java-8 default method with the same signature (as in your example) the implementing class is obliged to override the method. The class can still access the default method using I1.super.getGreeting();. It can access either, both or neither. So the following would be a valid implementation of C1

public class C1 implements I1, I2{
    public static void main(String[] args)
    {
        System.out.println(new C1().getGreeting());
    }

    @Override //class is obliged to override this method
    public String getGreeting() {
        //can use both default methods
        return I1.super.getGreeting()+I2.super.getGreeting();
    }

    public String useOne() {
        //can use the default method within annother method
        return "One "+I1.super.getGreeting();
    }

    public String useTheOther() {
        //can use the default method within annother method
        return "Two "+I2.super.getGreeting();
    }


}

Solution 4

There is a case where this actually works according to the resolution rules. If one of the interfaces extends one of the others.

Using the example from above:

public interface I2 extends I1 {
    default String getGreeting() {
        return "Good Afternoon!";
    }
}

The result would be:

Good Afternoon!

However, I believe this is going to be a big problem. The whole reason for default interfaces is to allow library developers to evolve apis without breaking implementers.

Understandably they don't allow the methods to compile without the inheritance structure via extension because a library developer could potentially hijack behavior.

However, this has the potential to be self defeating. If a class implements two interfaces that are not related from a hierarchical view, but both define the same default method signature, then the class that extends both interfaces will not compile. (as demonstrated above)

It is conceivable that two different library developers could decide to add default methods at different times using common signatures; in fact it is probable that this will happen in libraries that implement similar concepts such as math libraries. If you happen to be the sorry soul implementing both interfaces in the same class you will be broken on update.

Solution 5

I believe the rule is that the class implementing the duplicate default methods 'must' override the implementation.. The following compiles and runs fine...

public class DupeDefaultInterfaceMethods {

interface FirstAbility {
    public default boolean doSomething() {
        return true;
    }
}

interface SecondAbility {
    public default boolean doSomething() {
        return true;
    }
}

class Dupe implements FirstAbility, SecondAbility {
    @Override
    public boolean doSomething() {
        return false;
    }
}

public static void main(String[] args) {
    DupeDefaultInterfaceMethods ddif = new DupeDefaultInterfaceMethods();
    Dupe dupe = ddif.new Dupe();
    System.out.println(dupe.doSomething());

    }
}

> false
Share:
30,281
kavai77
Author by

kavai77

Java, what else?

Updated on October 16, 2020

Comments

  • kavai77
    kavai77 over 3 years

    Suppose I have two interfaces:

    public interface I1
    {
        default String getGreeting() {
            return "Good Morning!";
        }
    }
    
    public interface I2
    {
        default String getGreeting() {
            return "Good Afternoon!";
        }
    }
    

    If I want to implement both of them, what implementation will be used?

    public class C1 implements I1, I2
    {
        public static void main(String[] args)
        {
            System.out.println(new C1().getGreeting());
        }
    }