【问题标题】:Why there is ambiguous reference to overloaded definition in this code?为什么这段代码中对重载定义的引用不明确?
【发布时间】:2018-05-02 21:53:18
【问题描述】:

为什么这段代码中对重载定义的引用不明确?

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)

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

对重载定义的模糊引用,

[错误] 类型 B 中的两个方法 m (a: A, o2: Any)B

[error] 和类型 A 中的方法 m (a1: A, a2: A)A [error] 匹配 参数类型(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

感谢任何提示。

【问题讨论】:

    标签: scala overloading overload-resolution


    【解决方案1】:

    您说的完全正确 - A 中的 m 版本更具体,这实际上是问题所在。

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

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

    更好的编译消息可能是:

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

    【讨论】:

      猜你喜欢
      • 2011-06-10
      • 1970-01-01
      • 2020-06-14
      • 2010-12-14
      • 1970-01-01
      • 2023-04-01
      • 2016-05-18
      • 2012-11-17
      相关资源
      最近更新 更多