So this question is about inheritance and method overriding. Specifically: the case when a child class has a same-name method as the parent, but with a different signature, like:
class A has methodX(String arg)
class B extends A has methodX(int arg)
In normal cases the correct method will be called based on the argument.
But in the following code I've encountered some strange behavior which I can't really explain:
static class A {
public void method1() {
System.out.println("m1.A");
}
public void method4(A arg) { //Original method4
System.out.println("m4.A");
}
}
static class B extends A {
public void method1() {
System.out.println("m1.B");
}
}
static class C extends B {
public void method4(A arg) { //Override method4 from Class A
System.out.println("m4.C");
}
}
static class E extends C {
public void method1() {
System.out.println("m1.E");
}
public void method4(E arg) { //NO OVERRIDE: Same name, but different method4 than in class A or C
System.out.println("m4.E");
}
}
public static void main(String[] args) {
A va = new A();
B vb = new B();
C vc = new C();
E ve = new E();
//At this point everything is fine
ve.method4(ve); //Calls method4 from class E based on parameter type - CORRECT
ve.method4(va); //Calls method4 from class C based on parameter type - CORRECT
//After this code strange things happen
vc = new E();
vb = vc;
vb.method1(); //Output: m1.E; method1 from class E is called - CORRECT
vb.method4(vb); //Output: m4.C; method4 from class C is called - why?
vc.method1(); //Output: m1.E; method1 from class E is called - CORRECT
vc.method4(vc); //Output: m4.C; method4 from class C is called - why?
vc.method4(ve); //Output: m4.C; method4 from class C is called - why?
}
So the output of the programm above is:
m4.E
m4.C
m1.E
m4.C //why? Expected: m4.E
m1.E
m4.C //why? Expected: m4.E
m4.C //why? Expected: m4.E
The behaviour of
vb and vc
is what i cannot understand. Any ideas?
I'm guessing that you expected m4.E
to be printed. But don't forget that overload resolution is performed at compile-time, not at execution time.
Neither C
nor B
have a method4(E)
method available, so the compiler resolves the calls to the method4(A)
method... which isn't overridden by E
. All the calls you have m4.C // why?
in the question are calls to a method with signature method4(A)
, called on an instance of E
. Now E
doesn't override method4(A)
, so it's left with the implementation in C
, which prints m4.C
.
Nothing strange going on here at all.
See more on this question at Stackoverflow