简体   繁体   中英

Java: cannot access a protected member of the superclass in the extending subclass

I want some discussions about this, but I could not infer the answer for my case. Still need help.

Here is my code:

package JustRandomPackage;

public class YetAnotherClass{
    protected int variable = 5;
}
package FirstChapter;

import JustRandomPackage.*;

public class ATypeNameProgram extends YetAnotherClass{
    public static void main(String[] args) {

        YetAnotherClass bill = new YetAnotherClass();
        System.out.println(bill.variable); // error: YetAnotherClass.variable is not visible

    }
}

Some definitions following which, the example above seems to be confusing:

 1. Subclass is a class that extends another class.
 2. Class members declared as protected can be accessed from 
    the classes in the same package as well as classes in other packages 
    that are subclasses of the declaring class.

The question: Why can't I access the protected member ( int variable = 5 ) from a subclass YetAnotherClass instance ( bill object)?

Classes in other packages that are subclasses of the declaring class can only access their own inherited protected members.

package FirstChapter;

import JustRandomPackage.*;

public class ATypeNameProgram extends YetAnotherClass{
    public ATypeNameProgram() {
        System.out.println(this.variable); // this.variable is visible
    }
}

... but not other objects' inherited protected members.

package FirstChapter;

import JustRandomPackage.*;

public class ATypeNameProgram extends YetAnotherClass{
    public ATypeNameProgram() {
        System.out.println(this.variable); // this.variable is visible
    }

    public boolean equals(ATypeNameProgram other) {
        return this.variable == other.variable; // error: YetAnotherClass.variable is not visible
    }
}

bill is not part of the subclassed YetAnotherClass. bill is a separate YetAnotherClass.

Try int bill = this.variable; (inside a constructor) to access the subclass' members.

Your code will work if YetAnotherClass will be in the same package as ATypeNameProgram . As others wrote it won't work in other cases. Here is the working example.

package my.example;

public class MainClass extends MyAnotherClass {
    public static void main(String[] args) {
        MyAnotherClass bill = new MyAnotherClass();
        System.out.println(bill.value); // this will work
    }
}

package my.example;

public class MyAnotherClass {

    protected int value = 5;

}

A class Foo can only access the protected instance members of type Bar if and only if Bar is assignable to Foo . Ie, if we can write:

Foo foo = new Bar(); 

For example, say we have:

package a;

public class Base {
    protected int protectedField;
}

Then we can have this:

package b;

import a.Base;

public class Parent extends Base {
    void foo() {
        int i = this.protectedField;
    }
    void foo(Parent p) {
        int i = p.protectedField;
    }
    void foo(Child c) {
        int i = c.protectedField;
    }
}

class Child extends Parent { }

This will compile because all protectedField s are accessed via instances of Parent . Note that because a Parent reference can be a Child instance (ie, we can write Parent p = new Child(); ), we can access c.protectedField .

The following will not compile:

package b;

import a.Base;

public class Parent extends Base {
    void foo(Stepchild sc) {
        int i = sc.protectedField; // ERROR
    }
}

class Stepchild extends Base {}

because an instance of Stepchild is not an instance of Parent .

Somewhat confusingly, this won't compile either:

package b;

import a.Base;

public class Parent extends Base {}

class Child extends Parent {
    void foo(Parent p) {
        p.protectedField; // ERROR
    }
}

this is because a Parent object isn't a superclass or superinterface of Child , and so Child can't access its protected members.

If you ever have trouble remembering, just think of whether or not the type can be written to a reference of the type of the class. Eg, we can write:

Parent p = new Child();

but cannot write

Child c = new Parent();     // ERROR
Parent p = new Stepchild(); // ERROR

so Child won't have access to Parent 's protected members, and Parent won't have access to Stepchild 's protected members.

A couple final points:

Remember that protected access allows visibility among the package. In my experience, people forget this.

Finally, protected static members are always visible among the inheritance hierarchy.

You aren't creating an instance of the class that extend it, but of the parent class. Check the code below:

public class ATypeNameProgram extends YetAnotherClass{
    public static void main(String[] args) {

        YetAnotherClass bill = new YetAnotherClass();
        System.out.println(bill.variable); // error: YetAnotherClass.variable is not visible

        ATypeNameProgram a = new ATypeNameProgram();
        System.out.println(a.variable); //this will work

    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM