我一直试图了解隐式参数在 Scala 中是如何工作的。据我所知,隐式参数解析是这样的:
- 将对象显式传递给方法。
- 范围内定义的隐式定义。
- 用作隐式参数的类的伴随对象
然而,当我开始与懒惰的 vals 一起玩这个时,我有点吃惊。似乎懒惰的 val 只使用最后的解析规则。下面是一些示例代码来说明:
class Bar(val name:String)
object Bar { implicit def bar = new Bar("some default bar") }
class Foo {
lazy val list = initialize
def initialize(implicit f:Bar) = {
println("initialize called with Bar: '" + f.name + "' ...")
List[Int]()
}
}
trait NonDefaultBar extends Foo {
implicit def f = new Bar("mixed in implicit bar")
def mixedInInit = initialize
lazy val mixedInList = list
}
object Test {
def test = {
println("Case 1: with implicitp parameter from companion object")
val foo1 = new Foo
foo1.list
foo1.initialize
println("Case 2: with mixedin implicit parameter overriding the default one...")
val foo2 = new Foo with NonDefaultBar
foo2.mixedInList
val foo3 = new Foo with NonDefaultBar
foo3.mixedInInit
println("Case 3: with local implicit parameter overriding the default one...")
implicit def nonDefaultBar = new Bar("locally scoped implicit bar")
val foo4 = new Foo
foo4.list
foo4.initialize
}
}
调用Test.test
给出以下输出:
Case 1: with implicitp parameter from companion object
initialize called with Bar: 'some default bar' ...
initialize called with Bar: 'some default bar' ...
Case 2: with mixedin implicit parameter overriding the default one...
initialize called with Bar: 'some default bar' ...
initialize called with Bar: 'mixed in implicit bar'...
Case 3: with local implicit parameter overriding the default one...
initialize called with Bar: 'some default bar' ...
initialize called with Bar: 'locally scoped implicit bar' ...
为什么编译器在案例 2 中调用 mixInList 时没有发现混入了隐式 Bar。在案例 3 中,它在访问列表时也错过了本地定义的隐式 Bar。
有什么方法可以将隐式参数与不使用伴随对象中定义的隐式定义的惰性 val 一起使用?