Hi Mr. Tyler,
Thanks a lot for all the help and the feedback.
In this question I have the doubt that at runtime the actual object's methods should be called and not the reference value's methods. The actual objects are B and C. The method runNow() of A should not be called. Instead runNow() of B and C should be called.
Please help clarify.
Regards,
Shachi
As you correct that B and C are the actual objects we create by the following statement as given in the question:
A[] a= new B[]{new B(), new C()};
However, since B and C are sub-classes of A, these objects inherit stuff from A as well.
Let's take the iteration part given in the question, which goes as below:
A[] a=new B[]{new B(),new C()}; for(A aa:a) System.out.print(aa.runNow()+" ");
This would be theoretically equivalent to this:
A ar0 = new B(); A ar1 = new C(); System.out.println(ar0.runNow()); System.out.println(ar1.runNow());
Notice the reference type of ar0 and ar1 is A? That is so to map it with the reference type used in the for loop variable.
So when we have this kind of reference, where the reference type is a super-type and the actual object is a sub-type, the JDK, at the compile time, has to check if the method exists in the reference type itself. That's why you can't run a method that doesn't exist in the reference type, even though it exists in the actual object!
So, as the JVM checks the type A it finds this:
public class A{ private String runNow(){ return "High"; } }
See the private modifier? When the super class method is private, it is not visible to the sub class, and therefore, is not subjected to be overridden. Of course, you can have a similar method in one of your sub classes, but it cannot be considered as a valid overriding method. Nevertheless, none of the overriding rules apply.
Now, as the compiler realizes that this method is not subjected to be overridden, it compiles the code leaving instructions to the JRE for not to look ahead for matching methods in the actual object that would be overriding the runNow() method, because the theory of polymorphism doesn't apply in here. So at the run time, the JRE follows that instruction and runs the method in the superclass - A.runNow()!
In case if the method in the reference type were NOT private, the JVM knows that it could be overridden, in which cases it leaves an instruction for the JRE to look ahead for matching methods in the actual object which could be overriding that method. That way, the JRE invokes the method in the actual object despite the type of the reference on which it is being called upon. This is what we call polymorphism!
You can even map this with interfaces. Methods in an interface don't have any implementation body, because they never run. Instead, the compiler instructs the JRE to look ahead for overriding methods in the actual object.
By having the private keyword, we made it clear for the compiler that that method will never be overridden in a subclass.
Does this make it clear for you?
Yes it is clear now . Thanks a lot !!