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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3071720/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 16:12:58  来源:igfitidea点击:

Why can't my subclass access a protected variable of its superclass, when it's in a different package?

javapackagesaccess-modifiersprotected

提问by Amir Rachum

I have an abstract class, relationin package database.relationand a subclass of it, Join, in package database.operations. relationhas a protected member named mStructure.

我有一个抽象类,relation封装database.relation和它的一个子类,Join在包database.operationsrelation有一个名为 的受保护成员mStructure

In Join:

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

On lines

上线

this.copyStructure(mRelLeft.mStructure);

and

for (final Header header : mRelRight.mStructure) {

I get the following error:

我收到以下错误:

The field Relation.mStructure is not visible

字段 Relation.mStructure 不可见

If I put both classes in the same package, this works perfectly. Can anyone explain this issue?

如果我将两个类放在同一个包中,这将非常有效。任何人都可以解释这个问题吗?

采纳答案by OscarRyz

It works, but only you the children tries to access it ownvariable, not variable of other instance ( even if it belongs to the same inheritance tree ).

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

See this sample code to understand it better:

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

//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
    } 
}

If we try to compile using the withParent.parentVariablewe've got:

如果我们尝试使用withParent.parentVariable我们得到的编译:

Children.java:8: parentVariable has protected access in parentpackage.Parent
    System.out.print(withParent.parentVariable);

It is accessible, but only to its own variable.

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

回答by Lauri Lehtinen

If protected, your instance of Joincannot access the mStructurein other instances (relRight, relLeft) outside the package.

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

EDIT:

编辑:

The table hereexplains this situation fairly well. I marked the culprit in your question with []s

此处的表格很好地解释了这种情况。我用[]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

回答by Marcus Adams

A little known caveat about protected:

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

6.6.2 Details on protected Access

A protected member or constructor of an object may be accessed from outside the package in which it is declared only by code that is responsible for the implementation of that object.

6.6.2 受保护访问的详细信息

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

回答by user1039663

The problem is that you are accessing other instance protected member.

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

You can apply multiple solutions, for example if possible you can declare in the parent class these two methods:

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

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

And then in childs code replace:

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

this.copyStructure(mRelLeft.mStructure);

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

With:

和:

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

That should work. Now Relation has the responsibility to provide methods that allow operations with itself inners to its children. Probably the reason behind this policy is that children should not mess with parent's internals unless they are part of the same software bundle in order to limit incompatibilities.

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