5

让我们考虑这段代码:

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

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

在此处输入图像描述

注释掉该行后,为什么 Scala 无法找到A.A2String是否可以找到A.A2Int

如何解决这个问题?

谢谢阅读。

4

1 回答 1

3

不同之处在于,当您这样做时iWantString(a),编译器会从某个起点开始工作:您显式传递a,编译器知道它的类型是A。鉴于iWantString需要 aString而不是 a A,编译器将搜索从Ato的隐式转换String以插入它并使调用成功。隐式查找规则规定编译器必须(在其他地方)查找类的伴随对象,A因为类型A是转换的源类型。这是它找到隐式转换的地方A2String。你必须从中得到的是,它只是因为你传递了一个A编译器知道寻找隐式转换为伴生对象的实例A.

当您这样做iWantInt时,编译器没有理由查看A,因此它不会找到您的方法A2Int(并且由于范围内没有其他方法/值提供 type 的隐式值Int,编译然后失败)。

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

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

于 2014-03-31T14:51:54.270 回答