如何限制演员消息到特定的types?

在Akka中 ,除了使用使用RPC风格的编程模型的“Typed Actor”API之外,有没有办法将消息限制为actor的特定静态types?

我可以在Akka上使用消息传递风格,而不需要在actor边界处抛弃静态types安全吗?

例如,我想使用这样的代码:

sealed abstract class FooMessage case object Foo extends FooMessage case object Bar extends FooMessage class FooActor extends Actor[FooMessage] { def receive = { case Foo => () // OK // Would raise a compiler error: // case s: String => error("Can't happen, String is not a subtype of FooMessage") } } val fooActor = actorOf[FooActor] fooActor ! Foo // OK // Won't compile: fooActor ! "Hello" 

也许人们不得不扩展一些基本特征,或者有一个像Either这样的结构来允许系统级消息( Exit等)。

然后,你必须将消息types编码到Actor参数中,这会大大降低ActorRegistry之类的值。

而且,像“成为”(这是演员模式的基本要素)这样强大的机制,input信息的价值就不那么重要了。

由于Akka在消息与当前行为不匹配时不会泄漏内存,因此将“错误”消息发送给“错误”actor的风险并不相同。

另外,Actor本质上是dynamic的,所以如果你想使它们成为静态的,使用TypedActor(不是RPC,它就像普通的actor一样RPC,void方法是!调用,Future返回types是!!!和其他返回types是基于!!)

通常的做法是声明一个Actor可以在Actor的伴随对象中接收什么消息,这使得知道它可以接收什么是非常容易的。

这有帮助吗?

在斯卡拉stdlib有一个借口 ,使基本演员无types(这不适用于阿卡,因为它不支持嵌套接收,我记得)。 电梯反过来支持打字的演员。

但是,使用频道,仍然可以使用stdlib创build强types的演员:

 object TypedActor { def apply[A](fun: PartialFunction[A, Any]): OutputChannel[A] = { val sink = new SyncVar[Channel[A]] actor { val in = new Channel[A](self) sink set in loop { in react { case any => reply(fun(any)) } } } sink.get } } sealed abstract class FooMessage case object Foo extends FooMessage case object Bar extends FooMessage object Test { val fooActor = TypedActor[FooMessage]{ case Foo => println("OK") } fooActor ! Foo fooActor ! "Hello!" // doesn't compile -> Type mismatch; found: String("Hello!"); required: FooMessage; } 

实际上限制一个Actor只有单一types作为input并不是很有用。 我认为更有用的是以严格的方式列出可能的input。

有严格的参与者input( SynapseGrid )的方法:

 case class Contact[T](...) case class Signal[T](contact:Contact[T], data:T) 

在你的情况下,接口由一个input接点组成:

 val FooInput = contact[FooMessage]("FooInput") 

在SynapseGrid框架内,信号的处理由Builder定义:

 class FooActorBuilder extends SystemBuilder { inputs(FooInput, OtherInput) FooInput.foreach(fooMessage => () //OK ) OtherInput.foreach(...) } 

显然,不能用不兼容的types来构造Signal。 因此我们有编译时间检查。 在SynapseGrid中,有一个用于处理信号和联系人的DSL。 例如,从外部发送Foo或Bar:

 val SomeOtherContact = contact[Boolean]("SomeOtherContact") SomeOtherContact.map(flag => if(flag) Foo else Bar) >> FooInput 

当然可以简单地发送消息:

 val inputMessage = Signal(FooInput, Foo) actor ! inputMessage 

听起来Akka的Akka的Typed Channel支持就是为了解决这个问题,但是(根据评论 已经从版本2.3中的Akka中删除了 )。

在Akka 2.2.3的文档中,有一个很好的“devise背景”部分,讨论支持types化消息发送和响应的困难。

还有一个由Roland Kuhn, Akka Typed Channels:Implementing Type Calculations as Macros ( [YouTube] / [幻灯片] )的NEScala演讲,讨论了键入的频道的实现。