Scala: Dynamic Dispatch

Viewed 951

Consider this Scala code:

class X {
    def m(a:A) = a.f(this) + ", " + "m(a:A) in X"
}

class Y extends X {
    override def m(a:A) = a.f(this) + ", " + "m(a:A) in Y"
}

class Z extends Y

class A {
    def f(x:X):String = "f(x:X) in A"
    def f(y:Y):String = "f(y:Y) in A"
}

class B extends A {
    override def f(x:X):String = "f(x:X) in B"
    def f(z:Z):String = "f(z:Z) in B"
    def g(x:X):String = super.f(x) + ", " + "g(x:X) in B"
    def h(y:Y):String = B.g(y) + ", " + "h(y:Y) in B"
}

object B {
    def f(x:X) = "f(x:X) in ObjB"
    def g(y:Y) = f(y) + ", " + "g(y:Y) in ObjB"
    def g(z:Z) = f(z) + ", " + "g(z:Z) in ObjB"
}

class C extends B {
    override def f(y:Y):String = "f(y:Y) in C"
    def h(z:Z):String = super.h(z) + ", " + "h(z:Z) in C"
    def k(x:X):String = x.m(this) + ", " + "k(x:X) in C"
}

The question given is: Give the output of running the following program:

val z: Z = new Z; val x: X = new Y
val c: C = new C; val a: A = new B
println(a.f(x)); println(a.f(z))
println(c.g(z)); println(c.h(z))
println(c.k(x))

I cannot seem to fully understand the output given. Here's what I think happens:

println(a.f(x)) = "f(x:X) in B"
println(a.f(z)) = "f(z:Z) in B"
println(c.g(z)) = "f(y:Y) in A, g(x:X) in B"
println(c.h(z)) = "f(y:Y) in A, g(y:Y) in ObjB, h(y:Y) in B, h(z:Z) in C"
println(c.k(x)) = "f(y:Y) in C, m(a:A) in Y, k(x:X) in C"

Yet, when I actually put the code into REPL, I get a different result:

println(a.f(x)) = "f(x:X) in B"
println(a.f(z)) = "f(y:Y) in A"
println(c.g(z)) = "f(x:X) in A, g(x:X) in B"
println(c.h(z)) = "f(x:X) in ObjB, g(y:Y) in ObjB, h(y:Y) in B, h(z:Z) in C"
println(c.k(x)) = "f(y:Y) in C, m(a:A) in Y, k(x:X) in C"

Why is this? I know that it is something to do with how overloaded methods are selected, but I could not find a single resource that precisely specifies how to determine which methods are selected, and when. If someone could explain the exact process, I would be grateful.

1 Answers
Related