Zunächst eine Klarstellung der Terminologie: Wir weisen Child
einer Variablen vom Typ ein Objekt zu Parent
. Parent
ist eine Referenz auf ein Objekt, das zufällig ein Subtyp von Parent
a ist Child
.
Es ist nur in einem komplizierteren Beispiel nützlich. Stellen Sie sich vor, Sie fügen getEmployeeDetails
der Klasse Parent Folgendes hinzu:
public String getEmployeeDetails() {
return "Name: " + name;
}
Wir könnten diese Methode überschreiben, Child
um weitere Details bereitzustellen:
@Override
public String getEmployeeDetails() {
return "Name: " + name + " Salary: " + salary;
}
Jetzt können Sie eine Codezeile schreiben, die alle verfügbaren Details abruft, unabhängig davon, ob es sich bei dem Objekt um ein Parent
oder um Folgendes handelt Child
:
parent.getEmployeeDetails();
Der folgende Code:
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();
}
Wird zur Ausgabe führen:
Name: 1
Name: 2 Salary: 2000
Wir haben a Child
als Parent
. Es hatte ein spezielles Verhalten, das für die Child
Klasse einzigartig war , aber als wir getEmployeeDetails()
anriefen, konnten wir den Unterschied ignorieren und uns darauf konzentrieren, wie Parent
und Child
ähnlich sind. Dies wird als Subtyp-Polymorphismus bezeichnet .
In Ihrer aktualisierten Frage wird gefragt, warum Child.salary
nicht zugänglich ist, wenn das Child
Objekt in einer Parent
Referenz gespeichert ist . Die Antwort ist der Schnittpunkt von "Polymorphismus" und "statischer Typisierung". Da Java zur Kompilierungszeit statisch typisiert ist, erhalten Sie bestimmte Garantien vom Compiler, müssen jedoch im Austausch Regeln befolgen, da der Code sonst nicht kompiliert wird. Hier besteht die relevante Garantie darin, dass jede Instanz eines Subtyps (z. B. Child
) als Instanz seines Supertyps (z Parent
. B. ) verwendet werden kann. Beispielsweise wird Ihnen garantiert, dass beim Zugriff employee.getEmployeeDetails
oder employee.name
beim Definieren der Methode oder des Felds für jedes Nicht-Null-Objekt, das einer Variablen employee
vom Typ zugewiesen werden könnteParent
. Um diese Garantie zu gewährleisten, berücksichtigt der Compiler nur diesen statischen Typ (im Grunde den Typ der Variablenreferenz).Parent
), wenn er entscheidet, auf was Sie zugreifen können. Sie können also nicht auf Mitglieder zugreifen, die für den Laufzeittyp des Objekts definiert sind Child
.
Wenn Sie wirklich wollen , eine verwenden , Child
als Parent
dies ist eine einfache Einschränkung zu leben und Ihr Code für verwendbar sein Parent
und alle Subtypen. Wenn dies nicht akzeptabel ist, geben Sie den Typ der Referenz an Child
.