I'm studying Java 8, and I have encountered a behavior with default
methods I cannot understand completely.
First, an "old-school" Java snippet which compiles and runs perfectly:
abstract class A {
public void print() {
System.out.println("A");
}
}
interface B {
void print(); // implicitly public and abstract
}
class C extends A implements B {
public void useInheritedPrint() {
print(); // prints A
}
}
C
inherits an implemented print()
from A
and an abstract print()
from B
which is considered correctly implemented.
But if A
becomes an interface
with default
method print()
, as follows:
interface A {
default void print() { // implicitly public
System.out.println("A");
}
}
interface B {
void print(); // implicitly public and abstract
}
class C implements A,B {
public void useInheritedPrint() {
print(); // should print A
}
}
Even though C
still inherits print()
from A
, the compiler complains about the fact that C
is not abstract
(same thing does not happen if A
is a class as shown before). If C
becomes abstract
as follows :
abstract class C implements A, B {
public void useInheritedPrint() {
print();
}
}
then the compiler complains about the fact the C
inherits both a default
(from A
) and an abstract
print()
(from B
).
The solution is either to define an abstract print()
in C
, as:
class C implements A,B {
public void useInheritedPrint() {
print(); // should print A
}
public abstract void print(); // shall be implemented by a concrete subclass
}
Or to override print()
, as:
class C implements A,B {
public void useInheritedPrint() {
print(); // should print A
}
public void print() {
// do something
}
}
Does anyone know if there is a particular reason for this asymmetric behavior between inheriting a default method
from an interface
and inheriting it from a parent class?
Is deadly diamond of death involved here somehow (I can't see why)?