Reputation: 1
Can someone explain how does the compiler works out which method he should take
class All { /* ... */ }
class Most extends All { /* ... */ }
class Special extends Most { /* ... */ }
class Top {
public void m( All p ) { System.out.print("A "); }
}
class Middle extends Top {
public void m( All p ) { System.out.print("M "); }
public void m( Special p ) { System.out.print("L "); }
}
class Bottom extends Middle {
public void m( Most p ) { System.out.print("V "); }
public void m( Special p ) { System.out.print("X "); }
}
class Test {
public static void run() {
All all = new All();
Most most = new Most();
Special special = new Special();
Top x = new Middle();
Top y = new Bottom();
Middle z = new Bottom();
x.m( most );
x.m( special );
y.m( all );
y.m( special );
z.m( all );
z.m( most );
}
}
For example you see a class inheritance of top
, middle
and bottom
and all
, most
and special
in this code. If I run this I get the output of M M M M M M
.
I need to know why the compiler always takes the method m() of the middle class.
Why x.M(special)
doesn't print out L?
Why does y.M(all)
and y.M(special)
print out M again?
Upvotes: 0
Views: 93
Reputation: 1499860
There are two aspects involved here:
In your specific example, x.m(special)
needs to resolve a call with a target type of Top
(the compile-time type of x
) and an argument of Special
(the compile-time type of special
).
There's only one method called m
in Top
, and that's m(All)
, so that's what the compiler selects (after validating that there's an implicit conversion from Special
to All
). At execution time, the type of the object that x
refers to is Middle
, so it executes the implementation of m(All)
in Middle
. Likewise the compile-time type of y
is Top
, so the m(All)
signature is picked, and it doesn't matter that y
is actually an instance of Bottom
, because Bottom
doesn't override m(All)
.
Upvotes: 6