Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why an inherited default-method cannot implement another interface like an inherited class method? [duplicate]

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)?

like image 293
1d0m3n30 Avatar asked Apr 20 '26 18:04

1d0m3n30


1 Answers

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).

like image 163
JB Nizet Avatar answered Apr 23 '26 07:04

JB Nizet



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!