Reputation: 95
class X
class Y extends X
class Z extends Y
class M {
def f(x: X): String = "f with X at M"
def f(x: Y): String = "f with Y at M"
}
class N extends M {
override def f(x: Y): String = "f with Y at N"
def f(x: Z): String = "f with Z at N"
}
val z: Z = new Z
val y: Y = z
val x: X = y
val m: M = new N
println(m.f(x))
// m dynamically matches as type N and sees x as type X thus goes into class M where it calls "f with X at M"
println(m.f(y))
// m dynamically matches as type N and sees y as type Y where it calls "f with Y at N"
println(m.f(z))
// m dynamically matches as type N and sees z as type Z where it calls "f with Z at N"
Consider this code, I don't understand with the final call println(m.f(z)) doesn't behave as I wrote in the comments - is there a good resource for understanding how overloading works in Scala?
Thank!
Upvotes: 1
Views: 71
Reputation: 4832
When you do this
val m: M = new N
It means that m is capable of doing everything that class M can. M has two methods - first which can take X, other Y.
And hence when you do this
m.f(z)
Runtime is going to search for a method which can accept z (of type Z). The method in N is not a candidate here because of two reasons
M
N
does not override any method of M
which can accept an argument of type Z
. You do have a method in N
which can accept a Z
but that's not a candidate because it's not overriding anything from M
f
in M
which can accept a Y
this is because Z
ISA Y
You can get what your last comment says if
M
which takes argument of type Z
and then you override it in N
val m : N = new N
I think the existing questions on SO already elaborate this point.
Upvotes: 0
Reputation: 10661
Firstly overloading in Scala works the same as in Java.
Secondly, it's about static and dynamic binding. Let's find out what compiler see. You have m: M
object. Class M
has f(X)
and f(Y)
methods. When you call m.f(z)
compiler resolves that method f(Y)
should be called because Z
is subclass of Y
. It's a very important point: compiler doesn't know real class of m
object that's why it knows nothing about method N.f(Z)
. And it's called static binding: compiler resolves method's signature. Later, in runtime, dynamic binding happens. JVM knows real class of m
and it calls f(Y)
which is overloaded in Z
.
Hope my explanations are clearly enough to understand.
Upvotes: 2
Reputation: 84
class x
class Y extends X
class Z extends Y
class M {
def f(x: X): String = "f with X at M"
def f(x: Y): String = "f with Y at M"
}
class N extends M {
override def f(x: Y): String = "f with Y at N"
def f(x: Z): String = "f with Z at N"
}
val z: Z = new Z
val y: Y = z
val x: X = y
val m: M = new N
println(m.f(x))
// m dynamically matches as type N and sees x as type X thus goes into class M where it calls "f with X at M"
println(m.f(y))
// m dynamically matches as type N and sees y as type Y where it calls "f with Y at N"
println(m.f(z))
// m dynamically matches as type N and sees z as type Z where it calls "f with Z at N"
Because the function will be overloaded on N.so N is depends on m.f(y) .finally it is related with x and y that is reason z function will call
Upvotes: 0