= Solution
Replace the overloaded entry family by one forwarding method and introduce the second dispatch explicitly:
``
class X {
def dispatch(to: M): String = to.visit(this)
}
class Y extends X {
override def dispatch(to: M): String = to.visit(this)
}
class Z extends Y {
override def dispatch(to: M): String = to.visit(this)
}
class M {
def f(x: X): String = x.dispatch(this)
def visit(x: X): String = "f with X at M"
def visit(x: Y): String = "f with Y at M"
def visit(x: Z): String = "f with Z at M"
}
class N extends M {
override def visit(x: X): String = "f with X at N"
override def visit(x: Y): String = "f with Y at N"
override def visit(x: Z): String = "f with Z at N"
}
``
The original three calls still type-check because all their arguments are subtypes of `X`. They all refer to the same runtime `Z` object already; the change is how the operation discovers that runtime type. The first virtual call selects `Z.dispatch`, where `this` has static type `Z`, so overload resolution selects `visit(Z)`. The second virtual call selects `N.visit(Z)` from the receiver's runtime type. Thus <double dispatch> gives \b[`f with Z at N` on all three lines].
Back to article page