Подтвердить что ты не робот

Почему мой подкласс не может получить доступ к защищенной переменной своего суперкласса, если он находится в другом пакете?

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

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

4b9b3361

Ответ 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 несет ответственность за предоставление методов, позволяющих выполнять операции с самими собой для своих детей. Вероятно, причиной этой политики является то, что дети не должны взаимодействовать с родительскими внутренними элементами, если они не являются частью одного и того же пакета программного обеспечения, чтобы ограничить несовместимость.