Scala

时间:2015-12-07 21:36:15

标签: scala implicit scaldi

我是Scala的新手,并且一直在努力学习和理解隐式转换和参数,并遇到了一个让我感到困惑的场景。

对于上下文,我使用Scaldi在Akka应用程序中进行依赖注入,并希望有多个可注入的actor从抽象类继承。我相信我无法使抽象类成为一个特征,因为我们需要通过构造函数参数创建一个隐式Injector来利用框架。

一个非常人为的例子展示了我所看到的行为如下:

class SecretSauce {}

abstract class Base(implicit secretSauce: SecretSauce) {}

class Concrete extends Base {}

object Example extends App {
    ... // Setup Actor system, etc, etc
    implicit val secretSauce: SecretSauce = new SecretSauce()
}

我希望事情有效,但我得到了编译错误:

Unspecified value parameter secretSauce.
class Concrete extends Base {
             ^

如果我将隐式参数添加到具体类中,那么就可以了:

class Concrete(implicit secretSauce: SecretSauce) extends Base {}

我认为我的困惑源于隐式参数的工作原理 - 在我所描述的情况下,它们是不是由子类继承的?有人可以ELI5在我的例子中发生了什么,或者指向一个可以帮助澄清事情的参考?

谢谢!

2 个答案:

答案 0 :(得分:3)

确定Scala编译器查找implicits的确切规则有点复杂,但在大多数情况下,您只需要考虑隐含值可能来自的两个位置:

  1. 目前的范围。
  2. 所涉及的任何类型的伴侣对象。
  3. 这意味着这将编译:

    class SecretSauce {}
    
    object SecretSauce {
      implicit val secretSauce: SecretSauce = new SecretSauce()
    }
    
    abstract class Base(implicit secretSauce: SecretSauce) {}
    
    object Example extends App {
      class Concrete extends Base {}
    }
    

    或者这个:

    class SecretSauce {}
    
    abstract class Base(implicit secretSauce: SecretSauce) {}
    
    object Example extends App {
      implicit val secretSauce: SecretSauce = new SecretSauce()
    
      class Concrete extends Base {}
    }
    

    在您的版本中,当编译器到达此行时:

    class Concrete extends Base {}
    

    它将知道它需要找到隐式SecretSauce值,它将首先查看范围中该行的隐含值,然后查看SecretSauce中的隐含值伴侣对象(如果存在)。它也找不到,所以它拒绝编译你的代码。

答案 1 :(得分:1)

隐含参数从“解析”获得:

  • 当前范围中定义的隐含
  • 明确导入
  • 通配符导入

为了根据我的理解定义class Concrete,需要定义或导入隐式。

我在this SO answer找到了一个非常好的解释。