Почему мой подкласс не может получить доступ к защищенной переменной своего суперкласса, когда он находится в другом пакете? - PullRequest
30 голосов
/ 18 июня 2010

У меня есть абстрактный класс 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 не видно

Если я поместил оба класса в один пакет, это прекрасно работает. Кто-нибудь может объяснить эту проблему?

Ответы [ 4 ]

25 голосов
/ 18 июня 2010

Это работает, но только вы, дети, пытаетесь получить к нему доступ собственная переменная, а не переменная другого экземпляра (даже если она принадлежит тому же дереву наследования).

Посмотреть этот примеркод, чтобы понять это лучше:

//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);

Он доступен, но только для своей собственной переменной.

13 голосов
/ 18 июня 2010

Мало известное предостережение о защищен :

6.6.2 Сведения о защищенном доступе

Защищенный элемент или конструктор к объекту можно получить доступ снаружи пакет, в котором он заявлен только по коду, который отвечает за реализация этого объекта.

2 голосов
/ 18 июня 2010

Если 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
0 голосов
/ 31 июля 2017

Проблема в том, что вы обращаетесь к другому защищенному экземпляру.

Вы можете применить несколько решений, например, если возможно, вы можете объявить в родительском классе эти два метода:

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);
    }
  }
}

А затем в коде ребенка заменить:

this.copyStructure(mRelLeft.mStructure);

for (final Header header :mRelRight.mStructure) {
  if (!mStructure.contains(header)) {
    mStructure.add(header);
  }
}

С:

this.copyRelationStructure(mRelLeft);
this.mergeRelationStructure(mRelRight);

Это должно сработать. Теперь Relation несет ответственность за предоставление методов, которые позволяют своим дочерним элементам выполнять операции с самим собой. Вероятно, причина этой политики заключается в том, что дети не должны связываться с внутренними компонентами родителей, если они не являются частью одного и того же пакета программного обеспечения для ограничения несовместимости.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...