C1
and C2
will be in the p1
package:package p1;
public class C1 {
public int m() { return 1;}
}
public class C2 extends C1 {
public int m() { return 2;}
}
* This source code was highlighted with Source Code Highlighter .
Class C3
will be in a separate p2
package:package p2;
public class C3 extends p1.C2 {
public int m() { return 3;}
}
* This source code was highlighted with Source Code Highlighter .
We also need the test class p1.Main
with this main
method:public static void main(String[] args) {
C1 c = new p2.C3();
System. out .println(cm());
}
* This source code was highlighted with Source Code Highlighter .
Note that we call the class 1
method on an instance of the class C3
. As you might guess, this example will display "3".m()
in all three classes to default visibility:public class C1 {
/*default*/ int m() { return 1;}
}
public class C2 extends C1 {
/*default*/ int m() { return 2;}
}
public class C3 extends p1.C2 {
/*default*/ int m() { return 3;}
}
* This source code was highlighted with Source Code Highlighter .
Now the output will be "2"!Main
class, which makes the call, does not see the m()
method of the C3
class, since it is in a separate package. As for Main
, the chain of inheritance ends in C2
. But since C2
is in the same package, its m()
method overrides the corresponding C1
method. Not very intuitive, but so it works.C3.m()
modifier back to public
. What happens now?public class C1 {
/*default*/ int m() { return 1;}
}
public class C2 extends C1 {
/*default*/ int m() { return 2;}
}
public class C3 extends p1.C2 {
public int m() { return 3;}
}
* This source code was highlighted with Source Code Highlighter .
Now Main
sees the C3.m()
method. But oddly enough, the result is still "2"!C3.m()
does not redefine C2.m()
. You can think of it this way: the overriding method must have access to the method that it overrides (via super.m()
). However, in this case, C3.m()
does not have access to its base method, since it is in a different package. Therefore, C3
is considered part of a completely different chain of inheritance, not one that contains C1
and C2
. If we called C3.m()
directly from Main
, we would get the expected result "3".protected
- an interesting visibility modifier. It behaves as a default modifier for members of the same package and as public
for subclasses. What happens if we change all visibility to protected
?public class C1 {
protected int m() { return 1;}
}
public class C2 extends C1 {
protected int m() { return 2;}
}
public class C3 extends p1.C2 {
protected int m() { return 3;}
}
* This source code was highlighted with Source Code Highlighter .
I reasoned like this: since Main
not a subclass of any of our classes, then protected
, in this case, should behave the same as the default modifier and the result should be "2." However, it is not. The important point is that C3.m()
has access to super.m()
and, therefore, the actual output will be "3".super.m()
from it.public class C1 {
/*default*/ int m() { return 1;}
}
public class C2 extends C1 {
/*default*/ int m() { return 2;}
}
public class C3 extends p1.C2 {
/*default*/ int m() { return 3;}
}
public class C4 extends p2.C3 {
/*default*/ int m() { return 4;}
}
* This source code was highlighted with Source Code Highlighter .
Note that C4
is in the p1
package. Now change the code of the Main
class as follows:public static void main(String[] args) {
C1 c = new C4();
System. out .println(cm());
}
* This source code was highlighted with Source Code Highlighter .
Then he will print "4". However, super.m()
not accessible from C4
: if you add the annotation @Override
to C4.m()
, the code will not be compiled. At the same time, if we change the main
method topublic static void main(String[] args) {
p2.C3 c = new C4();
System. out .println(cm());
}
* This source code was highlighted with Source Code Highlighter .
then the result will again be "3". This means that C4.m()
overrides C2.m()
and C1.m()
, but not C3.m()
. This also makes the situation even more confusing, and the correct assumption is as follows: the subclass method overrides the base class method, if and only if the method in the base class is accessible from the subclass . Here, the “base class” refers to any ancestor, not necessarily the direct parent.protected
, you can break the code in a completely different place without even knowing it, because several chains inheritance will merge into one.Source: https://habr.com/ru/post/62602/
All Articles