当我的子类位于不同的包中时,为什么我的子类不能访问其超类的受保护变量?

时间:2010-06-18 17:11:16

标签: java packages access-modifiers protected

我在包relation中有一个抽象类database.relation,在包Join中有一个子类database.operationsrelation有一个名为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 个答案:

答案 0 :(得分:25)

它有效,但只有孩子们试图访问拥有变量,而不是其他实例的变量(即使它属于同一个继承树)。

请参阅此示例代码以更好地理解它:

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

它是可访问的,但仅限于它自己的变量。

答案 1 :(得分:13)

关于protected的一个鲜为人知的警告:

  

6.6.2有关受保护访问的详细信息

     

受保护的成员或构造函数   可以从外部访问对象   声明它的包   只有负责的代码   该对象的实现。

答案 2 :(得分:2)

如果protected,您Join的实例无法访问软件包外的其他实例mStructurerelRight中的relLeft

编辑:

here相当好地解释了这种情况。我用[] 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

答案 3 :(得分:0)

问题是您正在访问其他受实例保护的成员。

您可以应用多个解决方案,例如,如果可能,您可以在父类中声明这两个方法:

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有责任提供允许其子项内部操作的方法。这个政策背后的原因可能是孩子们不应该弄乱父母的内部,除非他们是同一软件包的一部分,以限制不兼容性。