Reputation: 2597
With this code:
public abstract class A {
private String runNow() {
return "High";
}
public abstract String cos();
static class B extends A {
public String runNow() {
return "Low";
}
public String cos() {
return "cos from B";
}
}
public static void main(String args[]) {
A[] a = new B[] {new B(), new C()};
for (A aa : a) {
System.out.println(aa.runNow() + " " + aa.cos());
}
}
}
class C extends A.B {
public String runNow() {
return "Out";
}
public String cos() {
return "cos from C";
}
}
Why is the runNow
method from class A
invoked and not from the subclasses?
Upvotes: 4
Views: 134
Reputation: 34618
As you were already told, the problem is that runNow()
is private. It is therefore not overridden, and accessing it through a reference of type A
would get you to the A
class's definition, whereas trying to access it through a B
reference would get the subclasses.
I would like to point out, though, that this "odd" behavior is only possible because the method that is doing all this (your main
method) is defined inside A
. If your main
method was in another class that has access to these classes, you'd get an error that indicates that the method is not reachable at all. If you think about that, it may be more clear to you why the methods runNow()
in B
and C
do not override the one in A
. From the point of view of any object outside of A, there is no runNow()
method at all - it's an implementation detail and not part of the contract of A
. Therefore, it cannot be overridden, and the runNow()
in B
and C
are just new methods that you don't have access to when you use B
and C
polymorphically as A
.
Upvotes: 1
Reputation: 15212
Why is the runNow method from class A invoked and not from the subclasses
private
methods are not inherited in subclasses. Therefore, they cannot be overriden. Since runtime-polymorphism only applies to overriden methods, the runNow
method from A
will always be called. Change the runNow
method in A
to a public
method and you will get the desired output since public
methods are inherited and can be overriden.
Upvotes: 1
Reputation: 99
It's because method runNow()
in class A is private, so in classes B and C you're not overriding it. And when you're calling method aa.runNow()
it's called directly from class A.
Try to do some experiment and change your method in class A to this:
private String runNow2() {
return "High";
}
public String runNow() {
return "High";
}
Also change your System.out
to this one:
System.out.println(aa.runNow() + " " + aa.cos() + " " + aa.runNow2());
Now the result will be as expected.
Hope it helps!
Upvotes: 1
Reputation: 1273
It is because runNow() is a private method in class A. Private methods are not inherited so could not be overridden.
private String runNow(){
return "High";
}
And also that you have created a reference of type A
A[] a=new B[]{new B(),new C()};
so the only runNow() which will be called to complete the call is of class A as the compiler does not know about runNow() methods in class B and C
Upvotes: 1
Reputation: 726529
Short answer is "because runNow()
is private
".
When you compile this call aa.runNow()
the compiler sees that class A
has runNow
method which is private, and that your code is calling this private method. Since private methods cannot be overriden, the compiler routs the call to A
's runNow()
method - the only one it knows to exist in this context.
The fact that B
and C
also introduce their methods by the same name does not matter to the compiler, because these methods are new in the subclasses. The compiler cannot consider them overrides without breaking encapsulation of class A
, which designated runNow
a private method.
Upvotes: 2