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