You get this result because your proc
methods do not override each other.
The easiest way to see this is to add an @Override
-annotation:
static class Z extends Y {
public Z() {
v += 9;
}
@Override
public void proc(Z p) {
System.out.println(34);
}
}
This will fail to compile with the error message
The method proc(Test.Z) of type Test.Z must override or implement a supertype method
It is a good idea to add this annotation whenever you intend to override a method - that way the compiler can check if you actually do.
To fix the error and override the method to get your expected output, you could change the type of the parameter to X
:
static class Z extends Y {
public Z() {
v += 9;
}
@Override
public void proc(X p) {
System.out.println(34);
}
}
Now it compiles again, and yields 34
.
What happened in your example is that, instead of overriding, your class Z
added an overloaded method void proc(Z p)
in addition to the void proc(X p)
method from X
. Overload resolution is based on the compile time type, therefore only the method from X
is available and gets chosen. This method is overridden in Y
, so that is what is actually executed at runtime.
Therefore, a different way to get your expected result is to leave X
, Y
and Z
unchanged, and change the reference type of x
to Z
:
public static void main(String[] args) {
Z x = new Z();
Y y = new Z();
Z z = new Z();
x.proc(z);//// 1
System.out.println(y.getV());
}
This version invokes the overloaded method in Z
, because it is the most specific overload for a parameter of type Z
.