Scala 中的隐式抽象 class 构造函数参数和继承
Implicit abstract class constructor parameter and inheritance in Scala
我是 Scala 的新手,一直在尝试学习和理解隐式转换和参数,但遇到了一个让我感到困惑的场景。
对于上下文,我正在使用 Scaldi 在 Akka 应用程序中进行依赖注入,并希望有多个可注入的 actor 继承自抽象 class。我相信我无法使抽象 class 恰恰成为特征,因为我们需要通过构造函数参数使隐式 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,就像这样,事情会起作用:
class Concrete(implicit secretSauce: SecretSauce) extends Base {}
我认为我的困惑源于隐式参数的工作方式——在像我描述的那种情况下,它们不是由子 classes 继承的吗?有人可以 ELI5 我的例子中发生了什么,或者给我指出可以帮助解决问题的参考吗?
谢谢!
隐式参数从"resolved"获取:
- 在当前作用域中定义的隐式
- 显式导入
- 通配符导入
据我了解,为了定义class Concrete
,需要定义或导入隐式。
我在this SO answer中找到了很好的解释。
确定 Scala 编译器在何处查找隐式的确切规则有点复杂,但在大多数情况下,您只需要考虑隐式值可能来自的两个位置:
- 当前范围。
- 涉及的任何类型的伴随对象。
这意味着这将编译:
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
伴生对象(如果存在)。它也没有找到,所以它拒绝编译你的代码。
我是 Scala 的新手,一直在尝试学习和理解隐式转换和参数,但遇到了一个让我感到困惑的场景。
对于上下文,我正在使用 Scaldi 在 Akka 应用程序中进行依赖注入,并希望有多个可注入的 actor 继承自抽象 class。我相信我无法使抽象 class 恰恰成为特征,因为我们需要通过构造函数参数使隐式 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,就像这样,事情会起作用:
class Concrete(implicit secretSauce: SecretSauce) extends Base {}
我认为我的困惑源于隐式参数的工作方式——在像我描述的那种情况下,它们不是由子 classes 继承的吗?有人可以 ELI5 我的例子中发生了什么,或者给我指出可以帮助解决问题的参考吗?
谢谢!
隐式参数从"resolved"获取:
- 在当前作用域中定义的隐式
- 显式导入
- 通配符导入
据我了解,为了定义class Concrete
,需要定义或导入隐式。
我在this SO answer中找到了很好的解释。
确定 Scala 编译器在何处查找隐式的确切规则有点复杂,但在大多数情况下,您只需要考虑隐式值可能来自的两个位置:
- 当前范围。
- 涉及的任何类型的伴随对象。
这意味着这将编译:
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
伴生对象(如果存在)。它也没有找到,所以它拒绝编译你的代码。