(РЕДАКТИРОВАТЬ: ответ они непременно дает практический совет, как избежать этой проблемы в вашем случае. В этом ответе приведены причины, по которым вы должны следовать этому совету, т. Е. Почему язык был разработан таким образом. )
Вы можете получить доступ только к защищенному члену другого объекта того же типа, что и код доступа (или подкласс), даже если этот член объявлен в супертипе.
Из Спецификации языка Java, раздел 6.6.2 :
Пусть C - класс, в котором
защищенный член m объявлен. Доступ
разрешено только в теле
подкласс S C. Кроме того, если Id
обозначает поле экземпляра или экземпляр
метод, то:
- Если доступ осуществляется по полному имени Q.Id, где Q - ExpressionName,
тогда доступ разрешен, если и
только если тип выражения Q
является S или подклассом S.
- Если доступ осуществляется с помощью выражения доступа к полю E.Id, где E является основным
выражением или вызовом метода
выражение E.Id (...), где E представляет собой
Основное выражение, то доступ
разрешено, если и только если тип E
является S или подклассом S.
Это позволяет типу получать доступ к членам, относящимся к его собственному дереву наследования, без ущерба для инкапсуляции других классов. Например, предположим, что у нас есть:
A
/ \
B Other
/
C
и A объявлен защищенным членом x
. Без правила, работающего так, как оно работает, вы можете получить инкапсуляцию, поместив элемент в Other
:
public int getX(A a)
{
return a.x;
}
и просто вызывая эту передачу в экземпляре B
или C
- член фактически станет общедоступным, потому что вы всегда можете обойти это, введя другой класс ... не очень хорошая идея. В соответствии с текущим правилом вам нужно будет создать подкласс B
или C
, что, в первую очередь, невозможно.