= Solution
Apply <overload selection followed by dynamic dispatch>: the receiver's <static type> determines visible signatures, and argument <static types> choose the overload. The receiver's <runtime type> then selects its override. A `super` call starts at the inherited implementation instead of redispatching to the override just entered.
For `c.f1(y)`, the `Y` overload is visible on `C`, so its body in `C` runs. For `a.f2(x)`, the `X` signature is selected and its override in `C` calls `C.f1(X)`. For `a.f2(y)`, the `Y` signature is selected; its body in `C` calls `super.f1(y)`. The superclass `B` has only `f1(X)`, so that call uses `B.f1(X)`.
For `b.f3(y)`, the <static type> `B` exposes only `f3(X)`. Its override in `C` calls `super.f2(x)`, entering `B.f2(X)`. The unqualified `f1(x)` inside that body still uses <dynamic dispatch> on the original `C` instance, so it calls `C.f1(X)`.
Finally `c.f4(x)` invokes the <companion object> `C`, which is a separate receiver extending `B`. Its `f3(X)` calls inherited `B.f2(X)`, whose `f1` call dispatches to `ObjC.f1(X)`.<Imperative Programming examination paper by the University of Oxford (2014)>[p. 10, Question 6(a), method bodies and calls]{ref}
The exact five output lines, including the final comma and space on each line, are:
``
f1(y:Y) in C,
f1(x:X) in C, f2(x:X) in C,
f1(x:X) in B, f2(y:Y) in C,
f1(x:X) in C, f2(x:X) in B, f3(x:X) in C,
f1(x:X) in ObjC, f2(x:X) in B, f3(x:X) in ObjC, f4(x:X) in C,
``
$$
\boxed{\text{Select the signature statically, then dispatch that signature dynamically}.}
$$
Back to article page