Java 8 doesn't provide the same solution to allow multiple inheritance which they gave to solve interface default methods
Asked Answered
C

3

3

Problem:

We know that Java doesn’t allow to extend multiple classes because it would result in the Diamond Problem where the compiler could’t decide which superclass method to use. With interface default methods the Diamond Problem were introduction in Java 8. That is, because if a class implements two interfaces, each defining the same default method, and the implementing class doesn’t override the common default method, the compiler couldn’t decide which implementation to chose.

Solution:

Java 8 requires to provide an implementation for default methods implemented by more than one interface. So if a class would implement both interfaces mentioned above, it would have to provide an implementation for the common default method. Otherwise the compiler would throw a compile time error.

Question:

Why is this solution not applicable for multiple class inheritance, by overriding common methods introduced by child class?

Conjuncture answered 21/12, 2016 at 7:14 Comment(0)
O
7

You didn’t understand the Diamond Problem correctly (and granted, the current state of the Wikipedia article doesn’t explain it sufficiently). As shown in this graphic,

A true diamond

the diamond problem occurs, when the same class is inherited multiple times through different inheritance paths. This isn’t a problem for interfaces (and never was), as they only define a contract and specifying the same contract multiple times makes no difference.

The main problem is not associated with the methods but the data of that super type. Should the instance state of A exist once or twice in that case? If once, C and B can have different, conflicting constraints on A’s instance state. Both classes might also assume to have full control over A’s state, i.e. not consider that other class having the same access level. If having two different A states, a widening conversion of a D reference to an A reference becomes ambiguous, as either A could be meant.

Interfaces don’t have these problems, as they do not carry instance data at all. They also have (almost) no accessibility issues as their methods are always public. Allowing default methods, doesn’t change this, as default methods still don’t access instance variables but operate with the interface methods only.

Of course, there is the possibility that B and C declared default methods with identical signature, causing an ambiguity that has to be resolved in D. But this is even the case, when there is no A, i.e. no “diamond” at all. So this scenario is not a correct example of the “Diamond Problem”.

Olivero answered 21/12, 2016 at 9:58 Comment(2)
I agree about the argument of shared state for the diamond problem, but non the less, if you would have support for multiple inheritance in Java you would have to deal with the problem of selecting one of multiple implementations of a single method. This problem is stated in the question and how it is solved for interfaces in Java 8. The same solution couldn't be guaranteed to be applied for classes. Or did I missed something?Uphill
@Harmlezz: as stated in the last paragraph, the problem of having to disambiguate between multiple inherited non-abstract methods is a problem of multiple inheritance in general, but it doesn’t require a common super type to show up, hence, is unrelated to the Diamond problem. You are right, that this is a problem that can’t be solved generally for non-interface classes the same way, but still, it isn’t the specific problem called “Diamond Problem”.Olivero
U
1

Methods introduced by interfaces may always be overriden, while methods introduced by classes could be final. This is one reason why you potentially couldn't apply the same strategy for classes as you could for interfaces.

Uphill answered 21/12, 2016 at 9:29 Comment(0)
S
0

The conflict described as "diamond problem" can best be illustrated using a polymorphic call to method A.m() where the runtime type of the receiver has type D: Imagine D inherits two different methods both claiming to play the role of A.m() (one of them could be the original method A.m(), at least one of them is an override). Now, dynamic dispatch cannot decide which of the conflicting methods to invoke.

Aside: the distinction betwee the "diamond problem" and regular name clashes is particularly relevant in languages like Eiffel, where the conflict could be locally resolved for the perspective of type D, e.g., by renaming one method. This would avoid the name clash for invocations with static type D, but not for invocations with static type A.

Now, with default methods in Java 8, JLS was amended with rules that detect any such conflicts, requiring D to resolve the conflict (many different cases exist, depending on whether or not some of the types involved are classes). I.e., the diamond problem is not "solved" in Java 8, it is just avoided by rejecting any programs that would produce it.

In theory, similar rules could have been defined in Java 1 to admit multiple inheritance for classes. It's just a decision that was made early on, that the designers of Java did not want to support multiple inheritance.

The choice to admit multiple (implementation) inheritance for default methods but not for class methods is a purely pragmatic choice, not necessitated by any theory.

Suggest answered 22/12, 2016 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.