= Solution
The printed lines are:
``
f with X at M
f with Y at N
f with Y at N
``
<Method overloading> first uses static types. The receiver `m` has static type `M`, whose available signatures are `f(X)` and `f(Y)`. Argument `x` selects `f(X)`; `y` selects `f(Y)`; and `z`, statically `Z`, also selects `f(Y)` because that is the most specific available applicable signature. `N.f(Z)` is not available through the static receiver type.
Only after a signature is selected does <dynamic dispatch> choose an override for the runtime receiver `N`. That class overrides `f(Y)` but not `f(X)`, explaining all three lines. The shared argument object's runtime class does not trigger a second overload-resolution pass.
Back to article page