Hola Mario, la verdad que la explicación esta bastante clara. Yo las pregunta que hay al final las he contestdo de esta manera;
A) No. Daría "ClassCastException", el compilador no sabe si la variable Vehiculo almacena un taxi o una ambulancia.
B)Si
E)El toString si esta sobre escrito
Un resumen que me he hecho yo es que un objeto "Hombre o Mujer" que herede de Persona, tiene además de las propiedades y metédos de su propia clase "Hombre o Mujer" las que hereda de Persona.
Pero un objeto Persona no puede recibir ni las propiedades ni los metédos de sus clases extendidas o "hijas", a no ser que un objeto declarado Persona he instanciado Mujer, tenga los metédos sobre escritos o hagas un "Molde".
Ejemplo;
((Mujer)Persona[0]).metodoMujer();
Corrigeme si estoy equivocado con esta reflexión
;
Ahora viendo esto, digo yo que en el Stack, que es donde se guarda las variables de referencia habría una variable Persona y una Mujer apuntando a un mismo objeto. Este Objeto si se declara como Persona tiene en el Head en un principio únicamente todos los metódos y propiedades de una Persona.
Si más tarde se le pasa una referencia de Mujer, ese objeto en memoria también tiene los métodos y propiedades de Mujer. Pero no puede acceder a ellos facilmente. Hay sobreescribir los métodos y se hace un casting, esto es lo raro entre "".
Por que si tu creas un objeto directamente Mujer o Hombre, que extienden a Persona, en memoria se crea un objeto con los métodos y propiedades tanto de Hombre y Mujer como de Persona. Lo lógico. Pero si esa variable "tipo Mujer" la metes en un objeto tipo Persona, deja de tener acceso a sus propiedades y métodos a no ser que ....
No se que sentido tiene el haberlo hecho asi.