为什么我们必须显式导入具有来自伴随对象的隐式参数的隐式转换?奇怪。

时间:2014-03-31 14:28:25

标签: scala implicit-conversion implicits companion-object

让我们考虑一下这段代码:

class A
object A{
  implicit def A2Int(implicit a:A)=1
  implicit def A2String(a:A)="Hello"
}

object Run extends App{
  implicit val a: A =new A

  import A.A2Int
  // without this import this code does not compile, why ?
  // why is no import needed for A2String then ?

  def iWantInt(implicit i:Int)=println(i)
  def iWantString(implicit s:String)=println(s)

  iWantInt
  iWantString(a)
}

它运行并打印:

1
Hello

现在,如果我们将该行注释掉

import A.A2Int

然后我们得到一个编译错误:

enter image description here

如果该行被注释掉了,为什么Scala找不到A.A2String会找不到A.A2Int

如何解决这个问题?

感谢阅读。

1 个答案:

答案 0 :(得分:3)

不同之处在于,当您执行iWantString(a)时,编译器将获得一些起点:您正在显式传递a,编译器知道该类型为A。 鉴于iWantString需要String而非A,编译器将搜索从AString的隐式转换,以便插入并生成A通话成功。 隐式查找规则声明编译器必须在类A的伴随对象中查找(以及其他位置),因为类型A2String是转换的源类型。 这是它找到隐式转换A的地方。 你必须得到的是,只是因为你传递了A的一个实例,编译器才知道要查找隐式转换到iWantInt的伴随对象。

当您执行A时,编译器没有理由查看A2Int,因此它不会找到您的方法Int(并且范围内没有其他方法/值)提供类型{{1}}的隐式值,然后编译失败)。

有关隐式查找规则的详细信息,请参阅 请参阅http://www.scala-lang.org/docu/files/ScalaReference.pdf(第7.2章)中的scala规范。这是最相关的摘录:

  

类型T的隐式范围由类的所有伴随模块(第5.4节)组成       与隐式参数的类型相关联的。