为什么在此代码中对重载定义存在含糊不清的引用?

时间:2018-05-02 21:53:19

标签: scala overloading overload-resolution

为什么在此代码中对重载定义有不明确的引用?

class A {
  def m(a1: A, o2: Any): A = {
    print("1")
    a1
  }

  def m(a1: A, a2: A): A = {
    print("2")
    a1
  }

  def m(o1: Any, o2: Any): Any = {
    print("3")
    o1
  }

  def m(o: Any): Any = {
    print("4")
    o
  }
}

class B extends A {
  def m(b1: B, o2: Any): A = {
    print("5")
    b1
  }

  override def m(a: A, o2: Any): B = {
    print("6")
    this
  }

  override def m(o1: Any, o2: Any): Any = {
    print("7")
    o1
  }

  def m(i: Int): Unit = { print("8") }
}

val a = new A
val b = new B

b.m(a, a)

上面的代码给出了编译错误:

  

对重载定义的模糊引用,

     

[error]类型B中的方法m(a:A,o2:Any)B

     

[error]和类型A中的方法m(a1:A,a2:A)A [错误]匹配   参数类型(A,B)

但我的理解是method m in class A of type (a1: A, a2: A)A更具体 比method m in class B of type (a: A, o2: Any)B

任何提示都表示赞赏。

1 个答案:

答案 0 :(得分:1)

您完全正确 - mA的版本更具体,实际上是问题所在。

由于您实际在m的实例(即b)上调用b.m(a, a),编译器首先检查是否存在与B中的签名匹配的方法。由于B确实有一个方法可以通过类型检查(即m(a: A, o2: Any): B)到目前为止这么好。但是,虽然编译器还会检查超类A,但它会找到更具体的m版本(即m(a1: A, a2: A): A)。

问题是您在m的实例上调用了B,但是您明确要求编译器找到一个带有两个A类型参数的方法。编译器现在不确定您实际打算执行哪个版本,因此编译错误。

更好的编译信息可能是:

“嘿,我在m的层次结构中找到了A的更高版本,更符合您的要求,但我发现您在{{1}上明确调用了m (不是B)所以我真的不知道现在选择哪一个 - 如果我只选择一个你可能无法得到你在运行时获得的结果,你最好检查一下。“