This is just a code I was practicing on my own when I came across a problem I couldn't follow.
Line 2 and line 3 are fine. What I am not able to understand is line 1 i.e c.disp() When the subclass is cast to the superclass type now the reference variable c is of type car right?So why is it not calling the superclass disp() method but instead calling the subclass' disp() method? I can understand the point of dynamic polymorphism when the code is as follows : i.e Car c=new Civic();//b'cos the objest is of type Civic but I am confused about how it works with casting Car c=(Car)(new Civic()); Can somebody please explain?
Howdy, This line: Car c=(Car)(new Civic()); doesn't mean anything, and isn't needed, since Civic already IS a subtype of Car. So you can just pretend it isn't there. You only need to cast when the compiler cannot tell for certain whether the object is actually castable to the Reference type. So think of that code as being identical to: Car c = new Civic(); Remember, polymorphism ALWAYS applies to the *real* object type, and NEVER to the reference type. The cast never affects the actual object type. That object is a Civic on the heap regardless of what you do. Casting never changes an object; it is simply a way to tell the compiler that, "Trust me, I know what I am doing, and this object over here CAN be referenced from this declared reference type..." (although it fails at runtime if you were LYING. For example: Dog extends Animal Cat extends Animal Animal a = new Cat(); Dog d = (Dog) a; The code above would compile because you put the cast in, and because 'a' is-a Animal, and Dog is-a Animal, so it is possible (as far as the compiler is concerned) that in fact 'a' might really be a Dog (or a subtype of Dog). So this would be a runtime failure, not a compile-time failure. Why? Because if somebody thinks they have a Dog, they are going to ask it to bark. d.bark(); And of course, Cats don't bark So, think of casting as something to tell the compiler that this object will pass the instance-of test at runtime. There is NOTHING you can do, ever, to change the type of the actual object. The only thing you are doing is changing the way someone *sees* and *treats* the object. I can say: Object o = new Dog(); Animal a = (Animal) o; Dog d = (Dog) a; All of these work, and there is still just ONE object, a Dog, on the heap. BUT... there are now three different reference types REFERRING to that same Dog. The Object reference, o, can call methods ONLY if they are part of class Object. So I can ask the Dog for his hashcode, but I can't ask him to bark, using 'o'. With Animal, I can ask the Dog to 'eat' (assuming that is in the Animal class), but I can't ask him to bark. If I want true "Dogness" from that object, I have to treat it as the Dog that it is, and cast it to the Dog so that I can call bark(), a method defined ONLY in the Dog class. And if I want the beFriendly() method, well, then I have to cast it to the Pet interface that Dog implements... Pet p = (Pet) d; p.beFriendly(); Reference type means: what you can ASK the object to do. Object type means: what it really CAN do. But with non-static methods, regardless of how you view the object (in other words, regardless of the reference type you're using to access the object using the dot operator), there is only ONE object on the heap, so you'll get that object's version of the overridden method. Always. Good question, though! cheers, Kathy
posted 15 years ago
Thank you so much Kathy for the wonderful explanation.