【发布时间】:2012-01-27 05:26:28
【问题描述】:
假设我们有只涉及局部范围的隐式参数查找:
trait CanFoo[A] {
def foos(x: A): String
}
object Def {
implicit object ImportIntFoo extends CanFoo[Int] {
def foos(x: Int) = "ImportIntFoo:" + x.toString
}
}
object Main {
def test(): String = {
implicit object LocalIntFoo extends CanFoo[Int] {
def foos(x: Int) = "LocalIntFoo:" + x.toString
}
import Def._
foo(1)
}
def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}
在上面的代码中,LocalIntFoo 胜过ImportedIntFoo。
有人可以使用“静态重载解析规则(第 6.26.3 节)”解释它是如何被认为更具体的吗?
编辑:
名称绑定优先级是一个令人信服的论点,但有几个问题尚未解决。 首先,Scala Language Reference 说:
如果有多个符合条件的参数与隐式参数的类型匹配,则将使用静态重载解析规则(第 6.26.3 节)选择最具体的参数。
其次,名称绑定优先级是将已知标识符 x 解析为特定成员 pkg.A.B.x,以防在范围内有多个名为 x 的变量/方法/对象。 ImportIntFoo 和 LocalIntFoo 的名称不同。
第三,我可以证明名称绑定优先级单独不起作用,如下所示:
trait CanFoo[A] {
def foos(x: A): String
}
object Def {
implicit object ImportIntFoo extends CanFoo[Int] {
def foos(x: Int) = "ImportIntFoo:" + x.toString
}
}
object Main {
def test(): String = {
implicit object LocalAnyFoo extends CanFoo[Any] {
def foos(x: Any) = "LocalAnyFoo:" + x.toString
}
// implicit object LocalIntFoo extends CanFoo[Int] {
// def foos(x: Int) = "LocalIntFoo:" + x.toString
// }
import Def._
foo(1)
}
def foo[A:CanFoo](x: A): String = implicitly[CanFoo[A]].foos(x)
}
println(Main.test)
将其放入test.scala 并运行scala test.scala,它会打印出ImportIntFoo:1。
这是因为静态重载决议(§6.26.3)说更具体的类型获胜。
如果我们假设所有符合条件的隐式值都被命名为相同,那么LocalAnyFoo 应该屏蔽了ImportIntFoo。
相关:
这是对隐式参数解析的一个很好的总结,但它引用了 Josh 的 nescala 演示而不是规范。他的演讲促使我对此进行研究。
编译器实现
【问题讨论】: