Inheritance and recursion
This is expected. This is what happens for an instance of B
.
class A { void recursive(int i) { // <-- 3. this gets called System.out.println("A.recursive(" + i + ")"); if (i > 0) { recursive(i - 1); // <-- 4. this calls the overriden "recursive" method in class B, going back to 1. } }}class B extends A { void recursive(int i) { // <-- 1. this gets called System.out.println("B.recursive(" + i + ")"); super.recursive(i + 1); // <-- 2. this calls the "recursive" method of the parent class }}
As such, the calls are alternating between A
and B
.
This doesn't happen in the case of an instance of A
because the overriden method won't be called.
Because recursive(i - 1);
in A
refers to this.recursive(i - 1);
which is B#recursive
in second case. So, super
and this
will be called in recursive function alternatively.
void recursive(int i) { System.out.println("B.recursive(" + i + ")"); super.recursive(i + 1);//Method of A will be called}
in A
void recursive(int i) { System.out.println("A.recursive(" + i + ")"); if (i > 0) { this.recursive(i - 1);// call B#recursive }}
The other answers have all explained the essential point, that once an instance method is overridden it stays overridden and there's no getting it back except through super
. B.recursive()
invokes A.recursive()
. A.recursive()
then invokes recursive()
, which resolves to the override in B
. And we ping pong back and forth until the end of the universe or a StackOverflowError
, whichever comes first.
It would be nice if one could write this.recursive(i-1)
in A
to get its own implementation, but that would probably break things and have other unfortunate consequences, so this.recursive(i-1)
in A
invokes B.recursive()
and so forth.
There is a way to get the expected behavior, but it requires foresight. In other words, you must know in advance that you want a super.recursive()
in a subtype of A
to get trapped, so to speak, in the A
implementation. It is done like so:
class A { void recursive(int i) { doRecursive(i); } private void doRecursive(int i) { System.out.println("A.recursive(" + i + ")"); if (i > 0) { doRecursive(i - 1); } }}class B extends A { void recursive(int i) { System.out.println("B.recursive(" + i + ")"); super.recursive(i + 1); }}
Since A.recursive()
invokes doRecursive()
and doRecursive()
can never be overridden, A
is assured that it is calling its own logic.