Hi Mayank,
when you say :
a.call(a) --> Since a is of type Animal, it looks into Animal class & finds the matching method which takes Animal as parameter & executes & prints "SuperAnimal" (overloading)
a.call(h) --> here again it finds the matching method in Animal which takes Horse as parameter (till here overloading), but since the matched method is already overridden in the subclass, so at runtime JVM invokes the true object's (Horse) version of the method rather than the reference type's (Animal)
I think your statement over here is a bit misleading. Actually, call to methods is determined at runtime & hence when the JVM finds that the reference "a" is pointing to a Horse object, it makes a call to the "call()" function in the Horse object. It never looks at the "call()" function in class A.
After this, it checks the method argument of "call()" function & accordingly calls the appropriate function which in the 1st case is :
which had been inherited from Animal but not overriden.
In the second case, it calls for the overriden "call()" function present in the Horse object & thus prints "Horse" & not "SuperHorse".
Only the call to the instance variables is resolved at compile time & not the methods. for ex cosider this code :
This code would print 10 because the compiler has decided at compile time itself that the value of Horse has to be taken from class Animal.
The same is not true for methods.