Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to invoke an interface's default implementation of a method in an overriding implementation?

Tags:

java

default

Suppose I have the following code:

interface HumanoidForm {
    default HumanoidForm reproduce() {
        <appropriate code for humanoid form reproduction>
    }
}

class Android extends Machine implements HumanoidForm {
    public HumanoidForm reproduce() {
        <appropriate code for android reproduction> // how to use HumanoidForm's default implementation here?
    }
}

Now suppose "appropriate code for android reproduction" is best described by using "appropriate code for humanoid form reproduction" as a sub-routine. How can I access "appropriate code for humanoid form" from within "appropriate code for android reproduction"? I can think of three ways, but none of them works:

  • Simply invoking reproduce() invokes the overriding implementation.
  • Writing ((HumanoidForm) this).reproduce() still invokes the overriding implementation.
  • Mimicking the re-use of implementations of methods in super classes by overriding methods, one may think of writing super.reproduce(). However, that refers to Machine's implementation of reproduce, which may not even exist.

So it seems there is no way to re-use the code in the default method for overriding. Is that really so?

like image 563
user118967 Avatar asked Jan 08 '23 13:01

user118967


2 Answers

HumanoidForm.super.reproduce();
like image 84
Michael D Avatar answered Jan 17 '23 05:01

Michael D


Actually, you can choose freely the existing implementation. Let me give you a scenario slightly more complicated than yours. To make things worse, all A,B & C has the same method signature.

interface A {
    default void doWork() {
       System.out.println("Default implementation From A");
    }
}

interface B{
    default void doWork() {
      System.out.println("Default implementation From B");  
    }   
}

class C{
    void doWork(){
        System.out.println("Default implementation From C");
    }       
}

Now, I create a subclass to C which implements A & B:

class Tester extends C implements A, B
{
    @Override public void doWork(){
        A.super.doWork();  //Invoke A's implementation
        B.super.doWork();  //Invoke B's implementation
        super.doWork();    //Invoke C's implementation
    }
}

The output will be:

Default implementation From A
Default implementation From B
Default implementation From C

when you run:

new Tester().doWork();
like image 38
user3437460 Avatar answered Jan 17 '23 05:01

user3437460