По-перше, уточнення термінології: ми присвоюємо Child
об’єкт змінній типу Parent
. Parent
є посиланням на об'єкт, який є підтипом Parent
, a Child
.
Це корисно лише в більш складному прикладі. Уявіть, ви додали getEmployeeDetails
до класу Батько:
public String getEmployeeDetails() {
return "Name: " + name;
}
Ми могли б замінити цей метод, Child
щоб надати більше деталей:
@Override
public String getEmployeeDetails() {
return "Name: " + name + " Salary: " + salary;
}
Тепер ви можете написати один рядок коду , який отримує будь-які деталі , які доступні, чи є об'єкт а , Parent
або Child
:
parent.getEmployeeDetails();
Наступний код:
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();
}
Результатом буде результат:
Name: 1
Name: 2 Salary: 2000
Ми використовували a Child
як Parent
. Він мав спеціалізовану поведінку, унікальну для Child
класу, але коли ми телефонували, getEmployeeDetails()
ми могли ігнорувати різницю та зосереджуватися на тому, як Parent
і Child
схожі. Це називається політипом підтипу .
Ваше оновлене запитання задає питання про те, чому Child.salary
недоступний, коли Child
об’єкт зберігається у Parent
посиланні. Відповідь - перетин "поліморфізму" та "статичного набору тексту". Оскільки Java статично набирається під час компіляції, ви отримуєте певні гарантії від компілятора, але ви змушені дотримуватися правил в обмін, інакше код не компілюється. Тут відповідною гарантією є те, що кожен екземпляр підтипу (наприклад Child
) може бути використаний як екземпляр його надтипу (наприклад Parent
). Наприклад, вам гарантується, що при доступі employee.getEmployeeDetails
або employee.name
метод або поле визначено для будь-якого ненульового об’єкта, який може бути призначений змінній employee
типуParent
. Щоб забезпечити цю гарантію, компілятор враховує лише той статичний тип (в основному, тип посилання на змінну Parent
), вирішуючи, до чого ви можете отримати доступ. Таким чином , ви не можете отримати доступ до будь-яких членам, які визначені на тип виконання об'єкта, Child
.
Коли ви справді хочете використовувати Child
як a, Parent
це просто обмеження для життя, і ваш код буде придатним для використання для Parent
всіх його підтипів. Коли це неприйнятно, вкажіть тип посилання Child
.