Hiya.
I was tying myself in knots with this over 10 years back when I was learning java and I've never had a proper reply from anyone. I used to work for Oracle and even tried emailing James Gosling direct about it, but never got a reply! :-D I can explain *most* but not all of this. The situation is that it is designed to work like this:
In java's polymorphism, when casting, if you create an object of a certain subclass type in a hierarchy, it STAYS at that type, forever. Whether you try to cast to the superclass, as in your example, or whether you use a superclass reference, like this: Car mycar = new CarSubClass() , you still cannot access the superclass version of a method - it will ALWAYS run the named method in the subclass, unless of course the method doesn't exist, in which case it definitely will run the superclass method of the same name, if it exists.
The exception is with shadowed fields. Say a superclass and subclass have two identically named fields with different values in. In this case, the superclass reference or an explicit upcast on the subclass object WILL access the value of the superclass field.
The situation gets complicated further when you deal with STATIC methods, as one replyer above has already pointed out - in this case, you can in fact cast to get a superclass function. The "workaround" to the non-static scenario above is to get at it via 'super,' but this is considered an antipattern.
The question remains - why was it designed this way? In what way is the object methods being set in stone considered "polymorphic?"
It will be instructive to consider this design scenario: The situation for me was made worse because I was "taught" java by a trainer who didn't understand this. He gave a "great" analogy ( which was totally wrong! ) of a JamesBond object. The idea was that it had two subclasses, PoshJamesBond and ScubaDivingJamesBond. The argument went that say you need to create a ScubaDivingJamesBond in a hurry to rescue somebody from an underwater base. It has a method greet() which says "Friend or Foe?" - This bond then completes his mission, but you don't want him reporting back to Q in his scuba gear saying "Friend or foe" - you want the greet() method in the PoshJamesBond to run, saying "morning miss Moneypenny." So the idea was that you could cast either up to get a default posh method or somehow back down the other branch to the PoshJameBond. But this is simply not how java works.
I have been told that java implements "reference" polymorphism and not "object" polymorphism. In java polymorphism, any subclass can always be "considered" as a supertype. This is useful for things like collections, being of a supertype generic class which means no instanceOf operator is needed. It is also massively useful in the "factory" design pattern. You know you often see in java books this kind of thing:
Car mycar = new SubCar() ?
I used to wonder, what's the point, suerly if you know you are creating a subcar, why not create the reference as a subcar reference? It will work the same... Its own methods will be called, unless it needs to inherit from superclass Car, and it works seamlessly in collections with a Car generic type. So what gives?
The answer is the factory pattern. In a factory, an object is manufactured of a DELIBERATELY UNKNOWN type. So the "end user client code programmer" might get an instance of a SubCar, ( a class written by the API programmer ) via the factory - but it will have a REFERENCE type ( return type effectively ) of Car. Now it could be that the API programmer wanted to hide a bunch of details in the SubCar class, and doesn't want the client programmer to know. So say Car has a documented method of "drive", the end user could then call carReference.drive() without knowing ( or caring ) that it is actually the subclass drive() that is running - it appears for all intents and purposes to be a generic Car. As such, code declarations like Car mycar = new SubCar() make perfect sense in factory API code, but little sense in "end user" code ( e.g. somebody writing a JDBC program ) in this case you could just use SubCar mycar = new SubCar() , because you would probably want the SubCar variable values as well as its methods, and not the superclass field values.
Please, if somebody is reading this who has a good knowledge of the precise difference between "reference polymorphism" and "object polymorphism" and could even give an example of an object-polymorphic language, and the advantages / disadvantages of the approaches, please update!
kind regards :-)