-1

In the past (Java 7 and before), Java classes and interfaces served different roles: classes for abstracting method implementation; interfaces for abstracting object structure. However, since Java 8, interfaces can now define a method implementation using default methods. This leads to a problem known as the "diamond problem".

An interface A with a method execute() is extended by interfaces B and C containing default implementations of execute(). If a class then implements B and C, there is ambiguity to which default implementation of execute() should be run.

interface A {
    public void execute();
}

interface B extends A {
    default void execute() { System.out.println("B called"); }
}

interface C extends A {
    default void execute() { System.out.println("C called"); }
}

class D implements B, C {
}

Given the class definitions above, when (new D()).execute() is executed, what will be printed (if anything): "B called", or "C called"?

Shuba
  • 376
  • 2
  • 6
  • 14
  • And your question is? – Mena Aug 23 '18 at 15:31
  • 3
    I'm voting to close this question as off-topic because this is not a question. It's an attempt to document an already known and documented side-issue since Java 8. – Mena Aug 23 '18 at 15:36
  • Just edited to properly define the question: which `execute()` implementation from `B` or `C` is called when `(new D()).execute()` is run. – Shuba Aug 23 '18 at 15:36
  • No need to ask this question, just try to compile it with your java compiler. – jaudo Aug 23 '18 at 15:37
  • Ah, did not see that one. – Shuba Aug 23 '18 at 15:40
  • Another related question: [Implementing two interfaces with two default methods of the same signature in Java 8](https://stackoverflow.com/questions/22685930/implementing-two-interfaces-with-two-default-methods-of-the-same-signature-in-ja) – LuCio Aug 23 '18 at 15:41

1 Answers1

0

Since there are two implementations for execute() in D, the compiler will have no idea which implementation to use. In other words, this program will not compile.

The Resolution

The solution is D needs to create a new implementation of execute(), such that when (new D()).execute() is called, the compiler directly calls execute() in D rather than trying (and failing) to figure out which implementation from B or C to run.

class D implements B, C { // D does not need to implement A, since B and C already do

    @Override
    public void execute() { // new implementation defined in A
        B.super.execute(); // calls execute() defined by B
        C.super.execute(); // calls execute() defined by C
    }

}

In this example, (new D()).execute() will print -

B called

C called

Notes

If B and C are both classes, D cannot exist as a child of B and C since Java doesn't allow multiple-inheritance. However, if B xor C are classes, D does not need to reimplement execute() since it is extensably defined in the parent class.

interface B extends A {
    default void execute() { System.out.println("B called"); }
}

class C implements A {
    public void execute() { System.out.println("C called"); }
}

class D extends C implements B { 
    // Will compile correctly since C provides the implementation for execute()

}

In this example, (new D()).execute() will print "C called".

D extends C so will use the method implementations of C if not overridden.

justcurious
  • 839
  • 3
  • 12
  • 29
Shuba
  • 376
  • 2
  • 6
  • 14