我是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在我的例子中发生了什么,或者指向一个可以帮助澄清事情的参考?
谢谢!
答案 0 :(得分:3)
确定Scala编译器查找implicits的确切规则有点复杂,但在大多数情况下,您只需要考虑隐含值可能来自的两个位置:
这意味着这将编译:
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)