代码之家  ›  专栏  ›  技术社区  ›  Amir Rachum

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

  •  30
  • Amir Rachum  · 技术社区  · 14 年前

    我上的是抽象课, relation 包内 database.relation 以及它的一个子类, Join 在包装中 database.operations . 关系 具有名为的受保护成员 mStructure .

    加入 :

    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) {
    

    我得到以下错误:

    field relation.mstructure不可见

    如果我把这两个类放在同一个包中,这就非常有效。有人能解释这个问题吗?

    4 回复  |  直到 7 年前
        1
  •  25
  •   OscarRyz    14 年前

    它能用,但只有你孩子才会尝试使用它 拥有 变量,而不是其他实例的变量(即使它属于同一继承树)。

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

    //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
  •  13
  •   OscarRyz    14 年前

    一个鲜为人知的警告 protected :

    6.6.2受保护访问的详细信息

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

        3
  •  2
  •   Lauri Lehtinen    14 年前

    如果 protected ,您的实例 Join 无法访问 mStructure 在其他情况下( relRight , 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
    
        4
  •  0
  •   user1039663    7 年前

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

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

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

    那应该管用。现在,关系有责任为其子代提供允许自身内部操作的方法。这项政策背后的原因可能是,除非孩子是同一个软件包的一部分,否则他们不应该与家长的内部搞混,以限制不兼容。