Почему мой подкласс не может получить доступ к защищенной переменной своего суперкласса, если он находится в другом пакете?
У меня есть абстрактный класс relation
в пакете database.relation
и его подкласс Join
, в пакете database.operations
. relation
имеет защищенный член с именем mStructure
.
В Join
:
public Join(final Relation relLeft, final Relation relRight) {
super();
mRelLeft = relLeft;
mRelRight = relRight;
mStructure = new LinkedList<Header>();
this.copyStructure(mRelLeft.mStructure);
for (final Header header :mRelRight.mStructure) {
if (!mStructure.contains(header)) {
mStructure.add(header);
}
}
}
В строках
this.copyStructure(mRelLeft.mStructure);
и
for (final Header header : mRelRight.mStructure) {
Я получаю следующую ошибку:
Поле Relation.mStructure не отображается
Если я помещаю оба класса в один и тот же пакет, это отлично работает. Может ли кто-нибудь объяснить эту проблему?
Ответы
Ответ 1
Он работает, но только вы, дети, пытаетесь получить к нему доступ собственную переменную, а не переменную другого экземпляра (даже если она принадлежит к одному дереву наследования).
Смотрите этот пример кода, чтобы лучше понять его:
//in Parent.java
package parentpackage;
public class Parent {
protected String parentVariable = "whatever";// define protected variable
}
// in Children.java
package childenpackage;
import parentpackage.Parent;
class Children extends Parent {
Children(Parent withParent ){
System.out.println( this.parentVariable );// works well.
//System.out.print(withParent.parentVariable);// doesn't work
}
}
Если мы попытаемся скомпилировать с помощью withParent.parentVariable
, мы получим:
Children.java:8: parentVariable has protected access in parentpackage.Parent
System.out.print(withParent.parentVariable);
Он доступен, но только для его собственной переменной.
Ответ 2
Немного известно о предостережении protected:
6.6.2 Сведения о защищенном доступе
Защищенный член или конструктор объект может быть доступен извне пакет, в котором он объявлен только по коду, который отвечает за реализация этого объекта.
Ответ 3
Если protected
, ваш экземпляр Join
не может получить доступ к mStructure
в других экземплярах (relRight
, relLeft
) вне пакета.
EDIT:
Таблица здесь довольно хорошо объясняет эту ситуацию. Я отметил виновника в вашем вопросе []
s
Access Levels
Modifier Class Package Subclass World
public Y Y Y Y
protected Y [Y] Y N
no modifier Y Y N N
private Y N N N
Ответ 4
Проблема в том, что вы обращаетесь к другому защищенному экземпляром члену.
Вы можете применить несколько решений, например, если возможно, вы можете объявить в родительском классе эти два метода:
protected void copyRelationStructure(Relation r) {
this.copyStructure(r.mStructure);
}
protected void mergeRelationStructure(Relation r) {
for (final Header header: r.mStructure) {
if (!mStructure.contains(header)) {
mStructure.add(header);
}
}
}
И затем в коде childs замените:
this.copyStructure(mRelLeft.mStructure);
for (final Header header :mRelRight.mStructure) {
if (!mStructure.contains(header)) {
mStructure.add(header);
}
}
С
this.copyRelationStructure(mRelLeft);
this.mergeRelationStructure(mRelRight);
Это должно сработать. Теперь Relation несет ответственность за предоставление методов, позволяющих выполнять операции с самими собой для своих детей. Вероятно, причиной этой политики является то, что дети не должны взаимодействовать с родительскими внутренними элементами, если они не являются частью одного и того же пакета программного обеспечения, чтобы ограничить несовместимость.