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.
nick woodward wrote:
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.
is this true? maybe i'm misunderstanding it, but i thought the JVM looks at the object at run time and checks the object type. the context of the quote is about checked exceptions, but it seems like the statement should stand regardless of context. but this doesn't back up my experience...
So the compiler must play safe and insist that Exception be caught (or re‑declared) instead of XYZException.He said it might throw an Exception and I can't guarantee to catch that with XYZException or IOException.
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 6).
Let's take a look at an example:
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.
nick woodward wrote:
I don't understand how or why the compiler assumes you're calling the superclass version of the method - because that isn't usually the case is it?
Campbell Ritchie wrote:Agree. The compiler cannot tell which subclass version you are going to call.At the end of line 1 the compiler does not know that you are going to assign that to a Cat object, and the only information it has is that it is an Animal. The only “safe” course of action is to assume that everything in animal is an Animal version. Since the rules say that an overriding method cannot declare any “new” [checked] Exceptions, the compiler can do this safely.
If you went for the subclass version which throws IOException (as in my post) and you got a different subtype whose method throws different Exceptions from IOE and XYZE, then your program would crash.
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.
You are compiling from left to right. When you get to the Animal declaration, the compiler has not yet looked at the bit about new Cat(), so it cannot “know” whether you are going to assign to a Cat or not.Now, even the human eye, which is much better at seeing such things than the compiler, cannot tell whether eat(); is being called on a Cat instance or a Dog instance.Now you don't know whether to catch PRQ exceptions or XYZ exceptions; the only kind you can catch is plain simple Exception.nick woodward wrote: . . . is there any particular reason why the compiler cannot know this when the assignment occurs? . . .
Answer to follow later.. . . An overriding method cannot throw new or broader exceptions, and must mirror the exception of the parent if a superclass reference type is used? are narrower exceptions therefore prohibited when using a superclass reference? (am going to go and try and test this myself )
edit: *and unchecked omissions are fine in the subclass.
i figured out what my confusion with this was:
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.
they don't emphasise that the compiler assumes it. my confusion was that i was thinking (and my test code demonstrated) the JVM in action.
got it.
thank you very much, both of you!
nick
Campbell Ritchie wrote:
You are compiling from left to right. When you get to the Animal declaration, the compiler has not yet looked at the bit about new Cat(), so it cannot “know” whether you are going to assign to a Cat or not.Now, even the human eye, which is much better at seeing such things than the compiler, cannot tell whether eat(); is being called on a Cat instance or a Dog instance.Now you don't know whether to catch PRQ exceptions or XYZ exceptions; the only kind you can catch is plain simple Exception.nick woodward wrote: . . . is there any particular reason why the compiler cannot know this when the assignment occurs? . . .
That is consistent with the general implementation of polymorphism: you check at compile time which methods are present in Animal and the exact version used depends on whether it is a Cat or a Dog. That would apply even if Animal were an abstract class.
Spot on.nick woodward wrote: . . . an overriding method cannot throw new or broader exceptions, . . .
Poop goes in a willow feeder. Wipe with this tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
|