Важно признать, что здесь точно один объект с одной ссылкой . Может быть заманчиво представить его так, как будто суперкласс является отдельным экземпляром Second, находящимся в вашем экземпляре Third, но это не так; нет способа сослаться на этот экземпляр, потому что он не существует.
Для ясности: Дело не в том, что в Третьем есть скрытый экземпляр Second, на который ссылается super
, а во Втором есть First, а в First есть Объект. Вместо этого есть один объект, который может вести себя как Объект, Первый, Второй или Третий. Независимо от типа локальной переменной или ссылки («статический тип»), сам экземпляр имеет «тип времени выполнения», который является третьим.
Единственное, что super
может сделать для вас, это преднамеренно вызвать члена, который принадлежит суперклассу (JLS 15.11.2) , который может быть скрыт переопределением или именованием. Здесь это ничего не делает, потому что getClass()
- это метод final
, объявленный в Object. getClass
имеет документацию о том, что он «возвращает класс времени выполнения этого объекта» ( docs ). Не может быть различной реализации, поэтому вы всегда получите тип Third, как и в своем вопросе.
ОБНОВЛЕНИЕ: В отличие от getClass
, equals
не является final
и может быть переопределено. Point.equals
гарантирует, что класс, возвращаемый getClass
, равен и x
и y
равны. Вместо того, чтобы писать совершенно другую реализацию equals
, Point3D использует определение Point для equals
и дополнительно проверяет, что поле z
равно, что работает, потому что Point проверяет, что object.getClass() == this.getClass()
, а не object.getClass() == Point.class
. Он не мог сделать это просто, вызывая equals
, потому что это использовало бы реализацию Point3D.equals
; вместо этого он должен вызвать super.equals
, чтобы увидеть, как Point будет вычислять equals
.
Однако я надеюсь, что это пример в уроке, потому что полиморфизм утверждает, что Point3D является-Point и может делать все, что может делать Point (см. Принцип замены Лискова ). Для Point и Point3D это может ввести в заблуждение: вы можете написать метод double distanceBetween(Point a, Point b)
, который работает, как ожидается, с использованием 2D-точек, но дает неверный результат при использовании 3D-точек. В реальных условиях вам нужно быть осторожным в отношении того, что ваша иерархия классов и что они подразумевают.