【问题标题】:'ambiguous reference to overloaded definition' for implicit conversions without Manifest没有清单的隐式转换的“对重载定义的模糊引用”
【发布时间】:2013-10-10 20:02:49
【问题描述】:

如果我不包含 Manifest,则会出现隐式转换的编译器错误:

import scala.language.implicitConversions

abstract class Thing[+A] {
  def get:A
}

case class SubThing[+A](a:A) extends Thing[A] {
  def get = a
}

object Thing {
  implicit def anyToThing[A](a:A):Thing[A] = SubThing(a)
}

object Funcs {
  def f(x:Thing[Int]) = x.get + 1
  def f(x:Thing[Double]) = x.get + 1.0
}

object Main {
  def main(args:Array[String]) = {
    println(Funcs.f(1))
  }
}

会给

error: ambiguous reference to overloaded definition,
       both method f in object Funcs of type (x: Thing[Double])Double
       and  method f in object Funcs of type (x: Thing[Int])Int
       match argument types (Int) and expected result type Any
println(Funcs.f(1))
              ^

但是,如果我在隐式转换中为 A 传入一个隐式清单:

import scala.language.implicitConversions

abstract class Thing[+A] {
  def get:A
}

case class SubThing[+A](a:A) extends Thing[A] {
  def get = a
}

object Thing {
  implicit def anyToThing[A:Manifest](a:A):Thing[A] = SubThing(a)
}

object Funcs {
  def f(x:Thing[Int]) = x.get + 1
  def f(x:Thing[Double]) = x.get + 1.0
}

object Main {
  def main(args:Array[String]) = {
    println(Funcs.f(1))
  }
}

使代码编译正常。为什么会这样?在我们的代码库中有一个真实的例子,如果你依赖于泛型情况下的隐式转换,它会给出很多“没有 T 清单”错误,通过显式创建包装类来消除这些错误;但是,如果我们可以从隐式转换中获取 Manifest,那将是理想的。为什么需要它,或者是否有其他方法可以在避免清单的同时完成相同的事情?

【问题讨论】:

    标签: scala


    【解决方案1】:

    这是由于 scala 自动将 Ints 提升为 Double 导致的,这使得隐式转换变得不明确。当包含清单时,它会创建一个隐式参数,使函数解析变得明确,就像 Ivan 提到的那样,使用 DummyImplicit 隐式参数来解决由于类型擦除导致的重载函数歧义。

    【讨论】:

      【解决方案2】:

      我相信会发生这种情况,因为一旦转换为 Thing,类型擦除就会启动,它不再是 Thing[Int] 或 Thing[Double],而是 Thing[_],因此以下方法重载不起作用。

      object Funcs {
        def f(x:Thing[Int]) = x.get + 1
        def f(x:Thing[Double]) = x.get + 1.0
      }
      

      清单是我的理解有点崩溃的地方,因为我从来没有过多地处理过它,但我想它会保留类型以便方法重载起作用。

      我相信你可以使用宏来解决这个问题,尽管这会阻止在编译器不确定是 Int 或 Double 的任何东西上调用 Funcs.f()。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-05-11
        • 1970-01-01
        • 1970-01-01
        • 2016-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多