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.
public class ATypeNameProgram extends YetAnotherClass{
public ATypeNameProgram() {
System.out.println(this.variable); // this.variable is visible
}
}
... but not other objects' inherited protected
members.
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
. I.e., 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 (i.e., 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. E.g., 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
}
}