如何在Akka Actor中实现receive()

时间:2014-02-25 23:05:27

标签: scala akka

我正在将Java代码中的Akka UntypedActors转换为他们的Scala等价物。

但是,我无法理解如何正确实现receive()抽象方法。 ScalaDoc有点令人困惑,我看到的大部分示例都涉及String消息!

我的Actor可以支持多种消息类型,到目前为止这是我的解决方案:

override def receive = {
    case message if message.isInstanceOf[ClassOne] => {
        // do something after message.asInstanceOf[ClassOne]
      }
    case message if message.isInstanceOf[ClassTwo] => {
      // do something after message.asInstanceOf[ClassTwo]
    }        
    case message => unhandled(message)
  }

有没有更好的方法来实现上述目标?

3 个答案:

答案 0 :(得分:10)

override def receive = {
  case c: ClassOne =>
      // do something after message.asInstanceOf[ClassOne]
  case c: ClassTwo =>
  // do something after message.asInstanceOf[ClassTwo]
  case message => unhandled(message)
}

如果你正在使用案例类,你可以变得更复杂。

case class ClassOne(x: Int, y: String)
case class ClassTwo(a: Int, b: Option[ClassOne])

override def receive = {
  case ClassOne(x, y) =>
      println(s"Received $x and $y")
  case ClassTwo(a, Some(ClassOne(x, y)) if a == 42 =>
      // do something
  case ClassTwo(a, None) =>
  case c @ ClassOne(_, "foo") => // only match if y == "foo", now c is your instance of ClassOne
}    

各种有趣的东西。

答案 1 :(得分:6)

receive的类型为is really just a PartialFunction[Any,Unit]表示您可以使用Scala的pattern match expressions - 事实上,您已经在做了,只是不完全简洁 。一个等同的terser,它也可以让你处理每种情况的匹配类型:

def receive = {
    case classOneMessage : ClassOne => {
        // do something
      }
    case classTwoMessage : ClassTwo => {
      // do something 
    }        
    case _ => someCustomLogicHereOtherWiseThereWillBeASilentFailure 
              //you can, but you don't really need to define this case - in Akka 
              //the standard way to go if you want to process unknown messages
              //within *this* actor, is to override the Actor#unhandled(Any) 
              //method instead
  }

阅读the tour articlethe already-linked tutorial以获取有关模式匹配的更多信息,尤其是在将此功能与案例类一起使用的情况下 - 此模式在使用Akka时会定期应用,处理here in the Akka manual时的示例the ActorIdentity case class

答案 2 :(得分:1)

receive是Scala中的常规部分函数。你可以在你的案例中写下这样的东西:

  case class Example(number: Int, text: String)

  override def receive = {
    case message: ClassOne =>
      // do something with ClassOne instance
    case message: ClassTwo =>
      // do something with ClassTwo instance
    case Example(n, t) =>
      println(t * n)
    case Example(n, t) if n > 10 =>
      println("special case")
  }

除非您的应用程序逻辑要求您处理所有可能的消息,否则您不必为未处理的消息包含特殊情况。

前两种情况只是按消息类型匹配,子类型也会匹配。最后一个不仅匹配类型Example,还使用模式匹配“解构”它。