32

我有一个抽象类,relation在 packagedatabase.relation和它的子类Join,在 package 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

4 回答 4

27

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

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

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

它是可访问的,但只能访问它自己的变量。

于 2010-06-18T17:36:32.357 回答
13

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

6.6.2 受保护访问的详细信息

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

于 2010-06-18T17:31:03.157 回答
2

如果protected,您的实例Join无法访问包外的mStructure其他实例 ( relRight, relLeft)。

编辑:

此处的表格很好地解释了这种情况。[]我用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
于 2010-06-18T17:17:52.993 回答
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);
    }
  }
}

然后在孩子的代码中替换:

this.copyStructure(mRelLeft.mStructure);

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

和:

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

那应该行得通。现在,Relation 有责任提供允许对其子对象进行自身内部操作的方法。可能这个政策背后的原因是,孩子不应该乱搞父母的内部结构,除非他们是同一个软件包的一部分,以限制不兼容。

于 2017-07-31T08:11:32.260 回答