将actor作为参数传递

时间:2015-12-27 16:19:54

标签: scala akka

例如,我有

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
}

2 个答案:

答案 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)