You are asking "Why does Java not support multiple inheritance of implementation?"
This is discussed in the Java Tutorials, Multiple Inheritance of State, Implementation, and Type, but I wanted to give a specific example of the problems of multiple inheritance of implementation (as well as a new language feature solution at the end).
Imagine two interfaces (in our proposed version of Java that allows interface method bodies) that define a method with the same name.
public interface FaceOne {
public void method() {
System.out.println("FaceOne Version");
}
}
public interface FaceTwo {
public void method() {
System.out.println("FaceTwo Version");
}
}
And a class implements both interfaces, but doesn't override the method.
public class Inheriter implements FaceOne, FaceTwo {
}
When I call Inheriter.method()
, which works since the class inherits the method from its ancestors, the problem arises: does the output print "FaceOne Version" or "FaceTwo Version"?
In addition, if the class were to override the method, but wanted to also call its ancestor's version using super
, the compiler would again have trouble choosing between a version of the method.
This is why Java does not support multiple inheritance of implementation.
As an aside, I think an elegant way to implement this into the language would be as follows:
Continue to force implementing classes to override their ancestor interface's methods. This solves the first problem of a non-overridden method.
Then, use a similar notation as that of accessing an enclosing instance for an inner class to access a specific ancestor interface with super
. The Inheriter class would then have multiple options:
Do not call super.method()
, but rather only use newly-defined implementation.
Use FaceOne.super.method()
to make the default inherited implementation output "FaceOne Version".
Use FaceTwo.super.method()
to make the default inherited implementation output "FaceTwo Version".
Use a combination of the above:
One implementation could be:
@Override
public void method() {
FaceOne.super.method();
FaceTwo.super.method();
System.out.println("Inheriter Version");
}
Outputting:
FaceOne Version
FaceTwo Version
Inheriter Version
Edit: According to this question this is apparently exactly how default implementations are structured in Java 8.