views:

179

answers:

7

Let says I have classes A, B and C

B extends A C extends B

all have public void foo() method defined.

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

I checked super.super.foo(); But it's invalid syntax.

How can I achieve this?

A: 

It's not possible, we're limited to call the superclass implementations only.

Andreas_D
(I was too much impressed by Aarons now deleted answer that I deleted mine two seconds after posting ;) - undeleted it even though there are much better answers available now)
Andreas_D
+5  A: 

You can't - because it would break encapsulation.

You're able to call your superclass's method because it's assumed that you know what breaks encapsulation in your own class, and avoid that... but you don't know what rules your superclass is enforcing - so you can't just bypass an implementation there.

Jon Skeet
Odd.. I remember that there was a way to call Object.toString() even if toString() was overloaded by a superclass. But `Type.this` doesn't compile. :-/
Aaron Digulla
@Aaron: I'm not sure about Object.toString() - were you thinking of `System.identityHashCode`?
Jon Skeet
@Jon: Never used that, I'm pretty sure that it was toString(). Object.super.toString() doesn't work either. Maybe it was a bug in an early Java version or something.
Aaron Digulla
A: 
Dubas
Re: "You need to cast yourself in C to A and call the method required." - Nope, that's not how dynamic dispatch works.
polygenelubricants
Casting doesn't change which overridden method is called - and indeed it shouldn't, as that would render polymorphism useless.
Jon Skeet
Casting won't work, since when calling a method it always calls the overwritten method of the actual runtime class (in this case C). Calling super in B.foo(), and then super in C.foo() is what you usually do (that would be the right way), to ensure that B gets to run any class specific code, as not to break anything in B that may be inherited by C. But sadly it might not fit what he's trying to do, in which case he'll have to rethink his design.
Andrei Fierbinteanu
+1  A: 

You can't do it in a simple manner.

This is what I think you can do:

Have a bool in your class B. Now you must call B's foo from C like [super foo] but before doing this set the bool to true. Now in B's foo check if the bool is true then do not execute any steps in that and just call A's foo.

Hope this helps.

Madhup
That's the wildest Java hack ever :)
Nikita Rybak
Jon Skeet's answer is best: this kind of functionality should not be enabled because it breaks encapsulation. Instead of addressing the _HOW_ to do something like this, we should address the _WHY_ would anyone even want to do something like this (and tear apart that argument for violating OOP principles).
polygenelubricants
@Nikita Rybak: People ask for things that should not be asked. Hence the answers that should not be given ;)
Madhup
@polygenelubricants : I am not challenging Skeet's answer. I do not dare too. I just gave my view point.
Madhup
It would seem to be thread unsafe. If you are going to do something like this you can put void foo ( boolean flag ) { if ( flag ) super . foo ( ) ; else this . foo ( ) ; } in class B.As for encapsulation, once you come up with some reason why class B should have a foo(boolean) method, then how it is implemented is an implementation detail.
emory
+1  A: 

You can't even use reflection. Something like

Class superSuperClass = this.getClass().getSuperclass().getSuperclass();
superSuperClass.getMethod("foo").invoke(this);

would lead to an InvocationTargetException, because even if you call the foo-Method on the superSuperClass, it will still use C.foo() when you specify "this" in invoke. This is a consequence from the fact that all Java methods are virtual methods.

It seems you need help from the B class (e.g. by defining a superFoo(){ super.foo(); } method).

That said, it looks like a design problem if you try something like this, so it would be helpful to give us some background: Why you need to do this?

Landei
It was not my requirement. I was just thinking out of my head all possibilites of playing around with inheritance and got this question. Thanks.. I got the answer
Harish
A: 

I smell something fishy here.

Are you sure you are not just pushing the envelope too far "just because you should be able to do it"? Are you sure this is the best design pattern you can get? Have you tried refactoring it?

lorenzog
A: 

The need to call method of the parent's super class means that your entities hierarchy is thought out not well enough - your child class inherits behavior that is not intrinsic for it (see Liskov substitution principle). Thus consider to extend class A instead of B or any other solution that will not break this principle.

Vitalii Fedorenko