【问题标题】:Implicit parameters resolution from super trait来自超级特征的隐式参数解析
【发布时间】:2012-05-12 21:47:09
【问题描述】:

我正在尝试使用隐式参数将依赖项“注入”到我的类中,如下所示:

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 }
}

这里,编译器从Bar 的伴随对象中的隐式val 向FooTrait 提供隐式参数。这样做:

scala> println((new FooTrait{}).go)
from object

给了我期望的结果。但是,如果我将 FooTrait 和另一个特征混合在一起,例如:

trait SuperFoo {
    implicit val superBar = new Bar{ val m = "from super" }
}

结果是一样的:

scala> println((new FooTrait with SuperFoo).go)
from object

我认为编译器会先查看SuperFoo,然后再尝试通过检查Bar 的伴随对象来解析隐式参数。这个blog post 声明:

对于应用隐式值有非常严格的规则 到一个隐式参数。一个简单的思考方法是 将使用“最接近”的定义。局部范围,封闭类, 父类,所需类型的伴生对象。

我是否遗漏了什么,或者这是 scalas 隐式参数的已知限制?

【问题讨论】:

    标签: scala implicit


    【解决方案1】:

    aBar 的调用在FooTrait 中定义。当这个 trait 编译时,本地范围、封闭类或父类中没有适当的隐式。当您稍后混合另一个特征时,编译器不会尝试重新查找隐含。所以它只是使用伴随对象的默认隐式。

    如果你重写方法go,你可以从SuperFoo获取值:

    scala> println((new FooTrait with SuperFoo {override def go = {aBar.m}}).go)
    from super
    

    您还可以重新定义您的类层次结构以从父 trait 中获取您的隐式:

    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" }
    }
    

    并以这种方式使用它:

    scala> println((new FooTrait with DefaultFoo).go)
    from object
    
    scala> println((new FooTrait with SuperFoo).go)
    from super
    

    【讨论】:

    • 我认为编译器在执行像new FooTrait with SuperFoo 这样的混合时会生成一个新类,并且SuperFoo 在层次结构中会更高。
    • 可以,但是如果FooTraitSuperFoo 已经编译并且您无法访问它们的源代码怎么办?为了实现你想要的,编译器应该重写方法go,用几乎相同的字节码替换它,其中调用aBar(Bar.objBar)替换为aBar(superBar)
    • 是的,我想这会很困难,但如果它有效的话真的很酷!也许这是一个不错的爱好编译器插件项目:)
    猜你喜欢
    • 1970-01-01
    • 2012-01-27
    • 1970-01-01
    • 1970-01-01
    • 2015-08-30
    • 1970-01-01
    • 2012-04-23
    • 2015-10-05
    • 2013-12-27
    相关资源
    最近更新 更多