我正在尝试使用隐式参数将依赖项"注入"到我的类中,如下所示:
trait Bar {
def m:String
}
object Bar {
implicit val objBar = new Bar{ val m = "from object" }
}
trait FooTrait {
def aBar(implicit bar:Bar) = bar
def go = { aBar.m }
}
Run Code Online (Sandbox Code Playgroud)
这里编译器FooTrait从Bar伴随对象中的隐式val 提供隐式参数.这样做:
scala> println((new FooTrait{}).go)
from object
Run Code Online (Sandbox Code Playgroud)
给我我期望的结果.但是,如果我混合FooTrait和另一个特征如:
trait SuperFoo {
implicit val superBar = new Bar{ val m = "from super" }
}
Run Code Online (Sandbox Code Playgroud)
结果是一样的:
scala> println((new FooTrait with SuperFoo).go)
from object
Run Code Online (Sandbox Code Playgroud)
我认为编译器会SuperFoo在尝试通过检查Bar的伴随对象来解析隐式参数之前查看.这篇博客文章指出:
有一个非常严格的规则,隐式值将应用于隐式参数.考虑它的一个简单方法是使用"最接近"的定义.本地范围,封闭类,父类,所需类型的伴随对象.
我错过了什么或者这是scalas隐含参数的已知限制吗?
呼叫aBar是在里面定义的FooTrait.当此特征编译时,本地范围,封闭类或父类中没有正确的含义.当您稍后混入其他特征时,编译器不会尝试重新发现隐含.所以它只使用来自伴随对象的默认隐式.
SuperFoo如果覆盖方法,则可以获取值go:
scala> println((new FooTrait with SuperFoo {override def go = {aBar.m}}).go)
from super
Run Code Online (Sandbox Code Playgroud)
您还可以重新定义类层次结构以获取隐式父级特征:
trait BarHolder {
implicit val superBar: Bar
}
trait FooTrait extends BarHolder {
def aBar(implicit bar:Bar) = bar
def go = { aBar.m }
}
trait DefaultFoo extends BarHolder {
val superBar = implicitly[Bar]
}
trait SuperFoo extends BarHolder {
val superBar = new Bar{ val m = "from super" }
}
Run Code Online (Sandbox Code Playgroud)
并以这种方式使用它:
scala> println((new FooTrait with DefaultFoo).go)
from object
scala> println((new FooTrait with SuperFoo).go)
from super
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5992 次 |
| 最近记录: |