Multiple Inheritance Ambiguity with Interface

15,804

Solution 1

The diamond problem only applies to implementation inheritance (extends in all versions of Java prior to Java 8). It doesn't apply to API inheritance (implements in all versions of Java prior to Java 8).

Since interface methods with matching type signatures are compatible, there is no diamond problem if you inherit the same method signature twice: matching method signatures simply coalesce instead. (And if the type signatures aren't the same, then you don't have the diamond problem either.)

In Java 7 and below, the only way to inherit implementation code was via the extends keyword, which restricts to at most one parent. Therefore there is no multiple implementation inheritance and the diamond problem does not exist.

Java 8 adds a new wrinkle because it allows interfaces to have implementation code. It still escapes the diamond problem by simply falling back to the previous behavior (no implementation inheritance) when you're implementing multiple interfaces with methods that have matching signatures.

Solution 2

To add to existing answers about Java8 multiple inheritance with interfaces (a.k.a. how Java still avoids the diamond problem):

There are three rules to follow:

  1. A class always wins. Class's own method implementation takes priority over default methods in Interfaces.

  2. If class doesn't have any: the most specific interface wins

enter image description here

  1. If above is not the case, inheriting class has to explicitly state which method implementation it's using (otherwise it won't compile)

enter image description here

Solution 3

Java overcomes this problem even though interfaces can have default implementations of methods, because the default implementation is either unambiguous (the one in class A) or the situation is solved by some rule (when class B or class C overrides the implementation from class A, see below).

When the supertypes of a class or interface provide multiple default methods with the same signature:

  • Instance methods are preferred over interface default methods.
  • Methods that are already overridden by other candidates are ignored. This circumstance can arise when supertypes share a common ancestor.

However, if two or more independently defined default methods conflict, or a default method conflicts with an abstract method, then the Java compiler produces a compiler error. You must explicitly override the supertype methods. In this case you could invoke any of the of the default implementations with the super keyword.

See also: How does Java 8' new default interface model works (incl. diamond, multiple inheritance, and precedence)?

Solution 4

Java doesn't support multiple inheritance, so the diamond problem doesn't arise. If B & C are interfaces, then there is no implementation in the interfaces. Even if B & C override the method in interface A (cannot be a class), the methods will have same signature. There is no ambiguity regarding which implementation to use, because there is no implementation.

Solution 5

With default methods in interface introduced in Java 8, multiple inheritance related problem may arise, there are 3 scenarios -

1- If implementing class overrides the default method and provides its own functionality for the default method then the method of the class takes priority over the interface default methods.

2-When class implements both interfaces and both have the same default method, also the class is not overriding that method then the error will be thrown.

3-In case when an interface extends another interface and both have the same default method, the inheriting interface default method will take precedence.

read more about it here.

Share:
15,804
Razib
Author by

Razib

Updated on June 07, 2022

Comments

  • Razib
    Razib almost 2 years

    We all know about the diamond problem regarding multiple inheritance -

       A
      / \
     B   C
      \ / 
       D
    

    This problem describe an ambiguous situation for class D. If class A has a method and both/either of B and/or C override the method then which version of method does D override?

    Is this problem also applicable for interfaces in Java? If not, how do Java interfaces overcome this problem?

  • vinay
    vinay about 9 years
    As Daniel Pryden said things get a little tricky with Java 8.
  • supercat
    supercat about 9 years
    I don't think Java 8 really escapes the diamond problem. If B:A, C:A, D:B and D:C, and B contains a default implementation for one of A's methods and C doesn't, then that implementation may be used in D, but from what I understand it would then be a breaking change for C to add a default implementation of that method.
  • Daniel Pryden
    Daniel Pryden about 9 years
    @supercat: Good point. Depending on your point of view, you could say that Java 8 does have the diamond problem, but just makes the complex cases compile-time errors so that the behavior is easier to reason about (compared with, say, C++).
  • supercat
    supercat about 9 years
    I don't think they're necessarily compile-time errors, since C's default implementation could have been added between the time code using D was compiled and the time the code is run. I don't remember what Java does in that case but for the scenario an implementation of D is compiled, A adds a member, a consumer of D which uses the new member is compiled, and then B is compiled with a default implementation. At that point, D's implementation and consumer will work. If C is compiled with a default implementation, though, I don't see any good course of action for the JVM.
  • Andreas
    Andreas over 7 years
    @supercat FYI: JVM will throw IncompatibleClassChangeError: Conflicting default methods if B and C both have default implementation, and D didn't override. It's both a compile error and a runtime error.
  • supercat
    supercat over 7 years
    @Andreas: I wonder how often it's necessary to add default implementations to a method which is declared in a parent interface? If default implementations could only be added to the interface wherein a method is declared, that would avoid deadly-diamond issues. On the flip side, it would be helpful to be able to specify multiple default-method overloads for an interface method and have Java bind to the first one which would be satisfied by an implementing class or, going further, allow an interface to specify that any class which can satisfy overloads for all its methods should be...
  • supercat
    supercat over 7 years
    ...regarded as implementing it. This would make it possible to e.g. define an interface StringishThing which could be "implemented" by String or by other user classes, and offered some useful core methods that are missing from CharSequence.
  • ashish pandey
    ashish pandey over 4 years
    No implementation in the interfaces is valid till Java 7 from Java 8 even interface can have a concrete method.
  • Dmytro Melnychuk
    Dmytro Melnychuk over 2 years
    Actually, first and third points describe that class implementation takes priority