在Akka Actors中堆叠多个特性

10
我正在创建多个扩展Actor的特性。然后我想创建一个Actor类,该类使用其中一些特性。但是,我不确定如何将所有特性的接收方法组合到Actor类的接收方法中。
特性:
请提供需要翻译的内容。
 trait ServerLocatorTrait extends Actor {
    def receive() = {
      case "s" => println("I'm server ")
    }
  }

  trait ServiceRegistrationTrait extends Actor {
    def receive() = {
      case "r" => println("I'm registration ")
    }
  }

演员:

class FinalActor extends Actor with ServiceRegistrationTrait with ServerLocatorTrait {
  override def receive = {
     super.receive orElse ??? <--- what to put here
  }
}
现在如果我向 FinalActor 发送 "r""s",它只会到达 ServerLocatorTrait - 这是最后添加的 trait。因此,它目前的工作方式是将 super 视为最后添加的 trait,在这种情况下是 ServerLocatorTrait问题:
如何将 FinalActor 中所有 traits 的接收方法组合起来?
PS-我看过带有 react 示例的 actor:http://www.kotancode.com/2011/07/19/traits-multiple-inheritance-and-actors-in-scala/,但那不是我需要的。

@cmbaxter 我不认为它可能是那个问题的重复。但也许那个原帖的作者可以使用我选择的解决方案。 - Adrian
1个回答

17

我不确定是否可以合并接收方法,因为那将涉及调用超级的超级以获取 ServiceRegistration receive 方法。这也会非常令人困惑。

另一种方法是在特征中为 receive 方法赋予不同的名称。

trait ServerLocatorTrait extends Actor {
  def handleLocation: Receive = {
    case "s" => println("I'm server ")
  }
}

trait ServiceRegistrationTrait extends Actor {
  def handleRegistration: Receive = {
    case "r" => println("I'm registration ")
  }
}

class FinalActor extends Actor with ServiceRegistrationTrait with ServerLocatorTrait {
  def receive = handleLocation orElse handleRegistration
}

object Main extends App {

  val sys = ActorSystem()

  val actor = sys.actorOf(Props(new FinalActor))

  actor ! "s"
  actor ! "r"

  sys.shutdown()

}
你仍然可以使用你最初的方法,但是你必须为每个混合特质链接 super.receive
trait IgnoreAll extends Actor {
  def receive: Receive = Map()
}

trait ServerLocatorTrait extends Actor {
  abstract override def receive = ({
    case "s" => println("I'm server ")
  }: Receive) orElse super.receive
}

trait ServiceRegistrationTrait extends Actor {
  abstract override def receive = ({
    case "r" => println("I'm registration ")
  }: Receive) orElse super.receive
}

class FinalActor extends IgnoreAll with ServiceRegistrationTrait with ServerLocatorTrait

对我来说,后一种解决方案看起来很丑陋。

请参见以下链接,了解更详细的讨论:

使用PartialFunction链扩展Actors


我喜欢你的第一个解决方案,我想我会使用它(因为它显示了更多正在发生的事情); 我最初是在寻找类似于你的第二个解决方案的东西。 - Adrian
你的特征可以声明为:trait ServerLocatorTrait { this: Actor => .... },因为它们本身并不是实际的演员。使用这种语法,你可以说“这个特征将被混合到一个演员中”。 - martin-g

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接