views:

1284

answers:

4

Part of me thinks that this shouldn't be possible (even if it is), but I'll ask anyway.

Given the following class hierarchy (Grandparent and Parent are from a 3rd party and thus, not under my control), how would I override myMethod() in Child such that it bypasses the overridden implementation in Parent and invokes the one in Grandparent?

class Grandparent {
   public void myMethod() {
      // do stuff
   }
}

class Parent extends Grandparent {
   @Override public void myMethod() {
      super.myMethod();
      // do something else
   }
}

class Child extends Parent {
   @Override public void myMethod() {
      // ??? I want to *only* do what Grandparent did here
   }
}

Pretend that the Parent class provides a lot of other helpful behavior and is a crucial element of Child's hierarchy (in other words, I'm not looking for "make Child a subclass of Grandparent".

+1  A: 

Not possible.

I would create a final helper method in grandparent instead. And have this method (which is overridden) call that helper.

class Grandparent {
   public final void myHelperMethod() {
      // do stuff
   }
   public void myMethod() {
      myHelperMethod();
   }
}

class Parent extends Grandparent {
   @Override public void myMethod() {
      super.myMethod();
      // do something else
   }
}

class Child extends Parent {
   @Override public void myMethod() {
      // ??? I want to *only* do what Grandparent did here
      myHelperMethod();
   }
}
Mehrdad Afshari
Thanks. I was looking at doing something similar, but since I don't have "control" of the grandparent class, I'll effectively have to re-implement the method myself.
Steve Reed
@Steve Reed: If you only have control on the child class, there's not much else you could do.
Mehrdad Afshari
+2  A: 

Do you have control of the Parent class?

If so, could you add a method (myNewMethod) to the Parent that calls myMethod on Grandparent, and call myNewMethod from Child?

(I'm not a Java person, so don't know if you can only call a method in a superclass from an override of that method in a subclass)

class Grandparent {
   public void myMethod() {
      myHelperMethod();
   }
}

class Parent extends Grandparent {
   @Override public void myMethod() {
      super.myMethod();
      // do something else
   }
   public final void myNewMethod() {
      super.myMethod();
   }
}

class Child extends Parent {
   @Override public void myMethod() {
      // ??? I want to *only* do what Grandparent did here
      myNewMethod();
   }
}
Patrick McDonald
+4  A: 

The idea behind inheritance is that each class defines their methods how they need, so you don't need to be inspecting any code.

It seems like you're subclassing here just to re-use code, and that's not the idea of subclassing.

Maybe you should have a helper member to do some of the tasks you need, instead of subclassing, and have both "Child" and "Parent" classes extend "Grandparent".

The main question you need to ask yourself is: "Is Child really a descendant of Parent, Grandparent or neiter?" In other words, for every instance of Child, can I say it's a Parent?

If the answer is no, then you're subclassing wrongly: inheritance is supposed to mean something, not just code re-use (i.e. Ford IS ALSO a Car, not just "Ford" uses "Car" methods).

Seb
+1  A: 

Assuming that I couldn't touch the code in Parent or Grandparent and assuming that I'm not, as Seb suggested (and as Steve apparently agreed) simply misusing inheritance entirely:

I'd create a local instance of a Grandfather object (or a local class extending Grandfather, if it's abstract) and access its interpretation of myMethod() directly. Of course, depending on how much state information myMethod() is supposed to read and/or manipulate, the amount of work involved could be anything from "easy" to "excruciating".

It's an ugly solution, and, depending on how much state information is accessed, could be brittle as hell. But if Grandfather is reliably stable and/or myMethod() is fairly self-contained, it could work. The devil is in the details, as always.

I definitely agree with Seb that this is re-use, not inheritance. But, hey. Re-use is often a Good Thing.

BlairHippo