Calling super super class method

Viewed 40115

Let's say I have three classes A, B and C.

  • B extends A
  • C extends B

All have a public void foo() method defined.

Now from C's foo() method I want to invoke A's foo() method (NOT its parent B's method but the super super class A's method).

I tried super.super.foo();, but it's invalid syntax. How can I achieve this?

12 Answers

There is a workaround that solved my similar problem:

Using the class A, B, and C scenario, there is a method that will not break encapsulation nor does it require to declare class C inside of class B. The workaround is to move class B's methods into a separate but protected method.

Then, if those class B's methods are not required simply override that method but don't use 'super' within that method. Overriding and doing nothing effectively neutralises that class B method.

public class A {
    protected void callMe() {
        System.out.println("callMe for A");
    }
}

public class B extends A {
    protected void callMe() {
        super.callMe();
        methodsForB(); // Class B methods moved out and into it's own method
    }

    protected void methodsForB() {
        System.out.println("methods for B");
    }
}

public class C extends B {

    public static void main(String[] args) {
        new C().callMe();
    }

    protected void callMe() {
        super.callMe();
        System.out.println("callMe for C");
    }

    protected void methodsForB() {
        // Do nothing thereby neutralising class B methods 
    }
}

The result will be:

callMe for A
callMe for C

In my simple case I had to inherit B and C from abstract class, that incapsulates equal methods of B and C. So that

     A
     |
   Abstr
    / \
   B   C

While it doesn't solve the problem, it can be used in simple cases, when C is similar to B. For instance, when C is initialized, but doesn't want to use initializers of B. Then it simply calls Abstr methods.

This is a common part of B and C:

public abstract class Abstr extends AppCompatActivity {
    public void showProgress() {
    }

    public void hideProgress() {
    }
}

This is B, that has it's own method onCreate(), which exists in AppCompatActivity:

public class B extends Abstr {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); // Call from AppCompatActivity.
        setContentView(R.layout.activity_B); // B shows "activity_B" resource.
        showProgress();
    }
}

C shows its own layout:

public class C extends Abstr {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState); // Call from AppCompatActivity.
        setContentView(R.layout.activity_C); // C shows "activity_C" resource.
        showProgress();
    }
}

This is not something that you should do normally but, in special cases where you have to workaround some bug from a third party library (if it allow to do so), you can achieve calling a super super class method that has already been overwritten using the delegation pattern and an inner class that extends the super super class to use as a bridge:

class A() {
  public void foo() {
    System.out.println("calling A");
  }
}

class B extends A() {
  @Overwrite
  public void foo() {
    System.out.println("calling B");
  }
}

class C extends B() {
  private final a;

  public C() {
    this.a = new AExtension();
  }

  @Overwrite
  public void foo() {
    a.foo();
  }

  private class AExtension extends A {
  }
}

This way you will be able to not only call the super super method but also combine calls to other super super class methods with calls to methods of the super class or the class itself by using `C.super` or `C.this`. 
Related