I have a doubt about reference variables and method overriding.
On page 98, it says:
Polymorphic method invocations apply only to instance methods. You can always refer to an object with a more general reference variable type (a superclass or interface), but at runtime, the ONLY things that are dynamically selected based on the actual object (rather than the reference type) are instance methods. Not static methods. Not variables. Only overridden instance methods are dynamically invoked based on the real object's type.
But in the Exam Watch column on page 104, it says:
If a method is overridden but you use a polymorphic (supertype) reference to refer to the subtype object with the overriding method, the compiler assumes you�re calling the supertype version of the method. If the supertype version declares a checked exception, but the overriding subtype method does not, the compiler still thinks you are calling a method that declares an exception(more in Chapter 5).
Sorry. Just noticed this below the code sample of the above Exam Watch column.
This code will not compile because of the Exception declared on the Animal eat() method. This happens even though, at runtime, the eat() method used would be the Dog version, which does not declare the exception.
My doubt has been partly cleared, but I'm still confused. The method which is executed at runtime apparently belongs to the object's class, but what role does the compiler's assumption play here? Could someone explain the concepts involved?
Thanks a lot, Gunjan! From your example, I understood that the subtype's overridden method is called during runtime. But I have another doubt. The book says:
If a method is overridden but you use a polymorphic (supertype) reference to refer to the subtype object with the overriding method, the compiler assumes you�re calling the supertype version of the method.
Why does the compiler assume that the supertype version is called? How is it significant?
hi Mithun, i am still not clear with this. Can you please explain? The concept i am not clear about is: its a valid overidden method, then why is it that we will get a compiler error? Can you explain me different scenarios over where we will be expecting a compiler error and where we will not
I assume you are talking about the code in the Exam Watch section which I referred to earlier. This is how I understand it:
At runtime, both d.eat() and a.eat() will end up executing the same method, that is, the overridden version in the Dog2 class. The difference between the two function calls is the TYPE of the OBJECT REFERENCE used.
At compile time, the compiler assumes that a.eat() will call the eat method of the Animal class (since 'a' is an Animal reference) and that d.eat() will call the overridden version of the method in the Dog2 class (since 'd' is a Dog2 reference). So, even though a.eat() will call only the Dog2 version of the method at runtime, the compiler expects an appropriate function call that corresponds to the Animal version of eat(), which throws an exception. Therefore, the above code will compile if we enclose a.eat() in a try-catch block. BUT, I repeat, at runtime, only the Dog2 version of eat is called by a.eat(). This whole exception handling process we perform is merely for the compiler's satisfaction.