Assume we have two packages p1
and p2
and classes p1.M1
extended by p2.M12
as follows:
package p1;
public class M1 {
void method1() {
System.out.println("Method 1 called");
}
}
package p2;
import p1.M1;
public class M12 extends M1 {
void method2() {
System.out.println("Method 2 called");
}
}
Let's extend M12
with p2.B
:
package p2;
public class B extends M12 {
public void doSomething() {
method1();
method2();
}
}
This gives a compilation error as method1
, being package-protected within p1
is not visible in p2
. method2
is visible without problems.
Now let's extend p2.M12
with p1.A
:
package p1;
import p2.M12;
public class A extends M12 {
public void doSomething() {
method1();
method2();
}
}
Here I'm getting a compilation error for both method2()
(which is understandable) and method1()
:
My question is: why is the method1
which is package-protected in the package p1
is not visible in the class A
from the same package p1
?
First, what is a member of a class? The Java Language Specification states
A class body may contain declarations of members of the class, that is, fields (§8.3), methods (§8.4), classes (§8.5), and interfaces (§8.5).
And what are they composed of? The JLS states
The members of a class type are all of the following:
- Members inherited from its direct superclass (§8.1.4), except in class Object, which has no direct superclass
- Members inherited from any direct superinterfaces (§8.1.5)
- Members declared in the body of the class (§8.1.6)
It also mentions
Only members of a class that are declared
protected
orpublic
are inherited by subclasses declared in a package other than the one in which the class is declared.
All of this is reworded in the chapter on Inheritance
A class
C
inherits from its direct superclass all concrete methodsm
(both static and instance) of the superclass for which all of the following are true:
m
is a member of the direct superclass ofC
.m
ispublic
,protected
, or declared with package access in the same package as C`.- No method declared in
C
has a signature that is a subsignature (§8.4.2) of the signature ofm
.
The members of class M1
are method1
(and all the methods of Object
). M12
, being in a different package than its direct superclass, M1
, does not inherit method1
. The members of M12
are therefore only method2
.
The direct superclass of B
is M12
and is in the same package. It therefore inherits its member, method2
. B
knows nothing about method1
. If you had compiled your code with javac
, you would have received a cannot find symbol
compilation error instead. (It seems Eclipse is trying to guess what you were trying to do.)
Similarly, the direct superclass of A
is M12
, but is in a different package. It does not inherit method2
for that reason. A
doesn't know anything about method1
or method2
because it didn't inherit them. Both of those symbols cannot be found.
I think the easiest way to understand this behavior is the idea of "A is a M12"
When you declared the inheritance, you told A to get its behavior from M12, but M12 has no visible method called method1.
Let's do an experiment for fun:
public class M12 extends p1.M1 {
public void method1() {
System.out.println("Method 1 called");
}
void method2() {
System.out.println("Method 2 called");
}
}
Forget A.. when you declare such method, it is allowed - if you do not have an @Override on it. however, if M1 was:
public class M1 {
public void method1() {
System.out.println("Method 1 called");
}
}
you could have:
public class M12 extends p1.M1 {
@Override
public void method1() {
System.out.println("Method 1 called");
}
void method2() {
System.out.println("Method 2 called");
}
}
now, back to the original code for M1 and M2 with the method re-declared and method one made public:
public class M12 extends p1.M1 {
public void method1() {
System.out.println("Method 1 called");
}
public void method2() {
System.out.println("Method 2 called");
}
}
Then, you would be able to have
public class A extends M12 {
public void doSomething() {
method1();
method2();
}
}
ok, this is a trivial case, but would be missing to complete the sequense... bottom line, semantically, you could explain by the IS relationship.
If more is needed (https://docs.oracle.com/javase/tutorial/java/javaOO/accesscontrol.html):
The following table shows the access to members permitted by each modifier.
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
Visibility must flow through the class hierarchy.
The class hierarchy is A --> M12 --> M1
The since M1.method1
is not visible to M12
, it's not visible to any subclasses of it either, like A
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With