28

I have a class that extends a class that I need to overide, but I need to call that class's parent class. since I can't call super since that will execute the direct parent what is the best way to get the parent of my parent class?

I am sure this is a basic question, but its been a while since I have been doing any java.

class A
{
 public void myMethod()
 { /* ... */ }
}

class B extends A
{
 public void myMethod()
 { /* Another code */ }
}

class C extends B
{
 I need to call Class A here
 { /* Another code */ }
}
Jim Ferrans
  • 30,582
  • 12
  • 56
  • 83
dan.codes
  • 3,523
  • 9
  • 45
  • 59
  • 1
    Almost always using super is bad form. the only probable exception to this is an overiding method call what it overrided. In such cases it might be better to introduce an abstract or do nothing method and override that with the "original" method made final. This however means you only get one shot. Deep heirarchies are bad anyway... – mP. Jun 25 '10 at 13:07
  • Possible duplicate of [Java How to call method of grand parents?](http://stackoverflow.com/questions/2584377/java-how-to-call-method-of-grand-parents). Also related to http://stackoverflow.com/questions/586363/why-is-super-super-method-not-allowed-in-java – finnw Jun 25 '10 at 19:39

6 Answers6

38

You don't: it violates encapsulation.

It's fine to say, "No, I don't want my own behaviour - I want my parent's behaviour" because it's assumed that you'll only do so when it maintains your own state correctly.

However, you can't bypass your parent's behaviour - that would stop it from enforcing its own consistency. If the parent class wants to allow you to call the grandparent method directly, it can expose that via a separate method... but that's up to the parent class.

Jim Ferrans
  • 30,582
  • 12
  • 56
  • 83
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
11

You can't because it has been overridden by B. There is no instance of A inside C.

The thing is that you want to call a method of the class A, but from which instance? You have instantiated C, which is a class with a couple of own and inherited methods from B. If B is overriding a method of A, you can't access it from C, because the method itself belongs to C (is not a method of B, it has been inherited and now it's in C)

Possible workarounds:

B does not override myMethod()

C receives an instance of A and saves it as a class property.

myMethod() in A is static and you use A.myMethod() (I don't recommend it)

pakore
  • 11,395
  • 12
  • 43
  • 62
7

What you are asking is bad practice, What you are saying is that C is not a B, but an A. What you need to do is have C inherit from A. Then you can call super.

If not this is the only way...

public String A()
{
String s = "hello";
return s;
}

public String B()
{
String str = super.A();
return str;
}

public String C()
{
String s = super.B();
return s;
}
Romain Hippeau
  • 24,113
  • 5
  • 60
  • 79
  • 1
    Thanks, I see that I am doing this the wrong way and have to think of a better solution. I probably don't have to access that grand parents method to do what I want. – dan.codes Jun 25 '10 at 12:58
1

Besides what pakore answered, you could also chain super.myMethod() calls if that works for you. You will call myMethod() from A from the myMethod() in B.

class A {
   public void myMethod() {
     ....
   }
}

class B extends A {
   public void myMethod() {
     ....
     super.myMethod();
     ....
   }
}

class C extends B {
  public void myMethod() {
    ....
    super.myMethod(); //calls B who calls A
    ....
  }
}

You will eventually be calling myMethod from A, but indirectly... If that works for you.

  • That will work only if you want B.myMethod() to do exactly the same as A.myMethod(), which leads to the following question: why the hell did u override it in the first time? :) – pakore Jun 25 '10 at 12:59
  • @pakore: Sorry... to simple of an example. You call super.myMethod when you need to, based on some conditions, flags etc. I changed the example a little bit to make it clearer –  Jun 25 '10 at 13:03
  • Yeah I supposed you meant what you have updated now. Keep in mind that your solution is not the same as calling A.myMethod() from C, because, B.myMethod() is doing other things that maybe C doesn't want them to be done. C just wants A.myMethod() things to be done, not that AND a couple more. That's why I said that only works if A.myMethod()===B.myMethod(), and when it does, overriding makes no sense :). – pakore Jun 25 '10 at 13:07
  • @pakore: I agree with you! That is why I added the "If that works for you" part :D. If the OP is OK with this behavior then it is a solution, else it is not. Either way, he's breaking encapsulation rules here. Luckily he realized he's approaching this the wrong way. –  Jun 25 '10 at 13:15
0

You can't call A's method directly. In the few cases that I've hit this, the solution was to add a method in A to expose it's implementation. E.g.

class A
{
   public myMethod() {
        doAMyMethod();
   }

   void doAMyMethod() {
      // what A want's on doMyMethod, but now it's available
      // as a separately identifiable method
   }
}

class C extends B
{
   public void someStuff() {
      this.doAMyMethod();
   }
}

The scheme separates the public interface (doMyMethod) from the implementation (doAMyMethod). Inheritance does depend upon implementation details, and so this isn't strictly so bad, but I would try to avoid it if possible as it creates a tight coupling between the implementation in A and C.

mdma
  • 56,943
  • 12
  • 94
  • 128
0

What I do for this case is:

Make the object of class A inside the Class C and access the Class A there. This Example which clarifies more details:

class A{
int a;
}
class B extends A{
int a;
}
class C extends B{
int a; 
A obj = new A();
public void setData(int p,int q, int r) {

 this.a = p; //  points to it's own class
 super.a = q;// points to one up level class i.e in this case class B
 obj.a = r; // obj points the class A
}
 public void getData() {
    System.out.println("A class a: "+ obj.a);
    System.out.println("B class a: "+ super.a);
    System.out.println("C class a: "+this.a);
 }
}

public class MultiLevelInheritanceSuper {

 public static void main(String args[]){
    C2 obj = new C2();
    obj.setData(10, 20, 30);
    obj.getData();

 }

}

The output of this example is:

A class a: 30
B class a: 20
C class a: 10
susan097
  • 3,500
  • 1
  • 23
  • 30