Primero, una aclaración de la terminología: estamos asignando un Child
objeto a una variable de tipo Parent
. Parent
es una referencia a un objeto que resulta ser un subtipo de Parent
, a Child
.
Solo es útil en un ejemplo más complicado. Imagina que agregas getEmployeeDetails
a la clase Parent:
public String getEmployeeDetails() {
return "Name: " + name;
}
Podríamos anular ese método Child
para proporcionar más detalles:
@Override
public String getEmployeeDetails() {
return "Name: " + name + " Salary: " + salary;
}
Ahora puede escribir una línea de código que obtenga los detalles disponibles, ya sea que el objeto sea un Parent
o Child
:
parent.getEmployeeDetails();
El siguiente código:
Parent parent = new Parent();
parent.name = 1;
Child child = new Child();
child.name = 2;
child.salary = 2000;
Parent[] employees = new Parent[] { parent, child };
for (Parent employee : employees) {
employee.getEmployeeDetails();
}
Dará como resultado la salida:
Name: 1
Name: 2 Salary: 2000
Usamos un Child
como un Parent
. Tenía un comportamiento especializado exclusivo de la Child
clase, pero cuando getEmployeeDetails()
llamamos podíamos ignorar la diferencia y centrarnos en cómoParent
y Child
son similares. Esto se llama polimorfismo de subtipo .
Su pregunta actualizada pregunta por qué Child.salary
no es accesible cuando el Child
objeto está almacenado en una Parent
referencia. La respuesta es la intersección de "polimorfismo" y "tipificación estática". Debido a que Java se escribe estáticamente en el momento de la compilación, obtiene ciertas garantías del compilador, pero se ve obligado a seguir reglas a cambio o el código no se compilará. Aquí, la garantía relevante es que cada instancia de un subtipo (p Child
. Ej. ) Puede usarse como una instancia de su supertipo (p Parent
. Ej .). Por ejemplo, se le garantiza que cuando accede employee.getEmployeeDetails
o employee.name
el método o campo se define en cualquier objeto no nulo que podría asignarse a una variable employee
de tipoParent
. ., Para hacer esta garantía, el compilador considera solo ese tipo estático (básicamente, el tipo de referencia de variable Parent
) al decidir a qué puede acceder. Por lo tanto, no puede acceder a ningún miembro definido en el tipo de tiempo de ejecución del objeto,Child
.
Cuando realmente desee usar un Child
como, Parent
esta es una restricción fácil de usar y su código se podrá usar para Parent
todos sus subtipos. Cuando eso no sea aceptable, escriba el tipo de referencia Child
.