功能重载机制

时间:2016-06-01 12:43:09

标签: scala

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"

考虑一下这段代码,我不能理解最终调用println(mf(z))的行为与我在评论中写的不一样 - 是否有很好的资源来理解Scala中的重载是如何工作的?

感谢!

3 个答案:

答案 0 :(得分:2)

首先,Scala中的重载与Java中的重载相同。

其次,它是关于静态和动态绑定。让我们找出编译器看到的内容。你有m: M个对象。类M具有f(X)f(Y)方法。当您调用m.f(z)编译器时,应调用方法f(Y),因为ZY的子类。这是非常重要的一点:编译器不知道m对象的真正类,这就是为什么它对方法N.f(Z)一无所知。它被称为静态绑定:编译器解析方法的签名。稍后,在运行时,会发生动态绑定。 JVM知道m的真实类,并调用f(Y)中重载的Z。 希望我的解释显然足以理解。

答案 1 :(得分:0)

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"

因为函数将在N上重载,所以N取决于m.f(y)。最后它与x和y有关,这是z函数将调用的原因

答案 2 :(得分:0)

当你这样做时

val m: M = new N

这意味着m能够完成M级所能做的所有事情。 M有两种方法 - 第一种可以采用X,其他采用Y.

因此当你这样做时

m.f(z)

运行时将搜索一个可以接受z(类型为Z)的方法。由于两个原因,N中的方法不是候选者

  1. 引用属于M
  2. 类型
  3. 您的N没有覆盖 M的任何可以接受Z类型参数的方法。您N中有一个方法可以接受Z,但这不是候选人,因为它没有覆盖{{1}的任何内容}
  4. Mf的最佳匹配可以接受M这是因为Y ISA Z
  5. 如果

    ,您可以获得上次评论所说的内容
    1. 您在Y中定义一个方法,该方法接受M类型的参数,然后在Z
    2. 中覆盖它
    3. 您实例化类型为N的val,例如:N
    4. 我认为关于SO的现有问题已经阐明了这一点。