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

孤人 提交于 2019-11-26 09:39:16

问题


I have an abstract class, relation in package database.relation and a subclass of it, Join, in package database.operations. relation has a protected member named mStructure.

In 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

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


回答1:


It works, but only you the children tries to access it own variable, 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.parentVariable we've got:

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

It is accessible, but only to its own variable.




回答2:


A little known caveat about 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.




回答3:


If protected, your instance of Join cannot access the mStructure in other instances (relRight, relLeft) outside the package.

EDIT:

The table here explains this situation fairly well. I marked the culprit in your question with []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:


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.



来源:https://stackoverflow.com/questions/3071720/why-cant-my-subclass-access-a-protected-variable-of-its-superclass-when-its-i

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!