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)?
You need to implement print() in C:
class C implements A,B {
public void useInheritedPrint() {
print(); // should print A
}
@Override
public void print() {
A.super.print();
}
}
The rationale is that, if you inherit two possibly conflicting methods with the same signature, you need to explicitly implement the method and choose one of the implementations (or define a new one).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With