例如,我有
trait Logger {
def log(m: Message) = ???
}
如果我想传递Logger
作为参数,我会简单地调用def foo(l: Logger)
。
但如果我有
trait Logger {
def log(m: Message) = ???
def receive = {
case m: Message = log(m)
}
}
,我必须传递ActorRef
才能在其上调用!
/ ?
等。但这完全打破了类型安全性 - def log(ar: ActorRef)
,并且没有任何内容表明它应该是Logger
下面的。{/ p>
所以,最后我想打电话
class Foo(logger: Logger) {
def foo(m: Message) = logger ! message
}
答案 0 :(得分:4)
嗯,是的。这就是Akka的工作方式,因为演员可以改变行为。请参阅How to restrict actor messages to specific types?。
解决方案1:定义一个类似
的包装类case class LoggerActor(ar: ActorRef) {
def log(m: Message) = ar ! m
}
然后使用LoggerActor
,确保您拥有Logger
。当然,如果你想在任何地方都这样做,你可能想要以某种方式自动创建这些类。
解决方案2:使用Akka Typed。请注意它的实验性。我不会从那里复制文档。
解决方案3:使用Scalaz actor,它们从头开始输入。有关用法示例,请参阅https://github.com/scalaz/scalaz/blob/series/7.3.x/tests/src/test/scala/scalaz/concurrent/ActorTest.scala。对于你的情况,它可能是
val logger = new Logger { ... }
val loggerActor = new Actor[Message](logger.log)
答案 1 :(得分:-1)
您可以指定您的ActorRef也应该实现Logger:
def log(ar: ActorRef with Logger)