Scala 如何将参与者消息限制为特定类型?
在中,除了使用使用RPC风格编程模型的“类型化的参与者”API外,是否有其他方法将发送给参与者的消息限制为特定的静态类型 我可以在Akka中使用消息传递样式,而不在参与者边界上丢弃静态类型的安全性吗 例如,我想使用如下代码:Scala 如何将参与者消息限制为特定类型?,scala,actor,akka,Scala,Actor,Akka,在中,除了使用使用RPC风格编程模型的“类型化的参与者”API外,是否有其他方法将发送给参与者的消息限制为特定的静态类型 我可以在Akka中使用消息传递样式,而不在参与者边界上丢弃静态类型的安全性吗 例如,我想使用如下代码: sealed abstract class FooMessage case object Foo extends FooMessage case object Bar extends FooMessage class FooActor extends Actor[FooM
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"
也许你必须扩展一些基本特征,或者使用类似于的结构来允许系统级消息(Exit
,等等)。在Scala stdlib中,基本角色是非类型化的(这不适用于Akka,因为我记得它不支持嵌套接收)。反过来,Lift支持输入的演员跳出盒子
但是,使用通道,仍然可以使用stdlib创建强类型参与者:
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 ref中,这将大大降低ActorRegistry之类的值
此外,使用强大的机制,如“变成”(这是参与者模型的基础),键入消息的价值也会降低
由于Akka不会在消息与当前行为不匹配时泄漏内存,因此向“错误”参与者发送“错误”消息的风险也不相同
此外,参与者本质上是动态的,所以如果您想使它们成为静态的,请使用TypedActor(它不是RPC,它与常规参与者一样是RPC,void方法是!调用,未来返回类型是!!!其他返回类型基于!!)
通常的做法是在参与者的同伴对象中声明参与者可以接收哪些消息,这使得了解参与者可以接收哪些消息变得非常容易
这有帮助吗?实际上,限制一个参与者只有一种类型作为输入并不是很有用。对我来说,更有用的是以严格键入的方式列出可能的输入
有一种方法用于参与者()的严格类型化输入:
在您的情况下,接口由单个输入触点组成:
val FooInput = contact[FooMessage]("FooInput")
在SynapseGrid框架内,信号处理由Builder定义:
class FooActorBuilder extends SystemBuilder {
inputs(FooInput, OtherInput)
FooInput.foreach(fooMessage => () //OK
)
OtherInput.foreach(...)
}
显然,不能用不兼容的类型构造信号。因此,我们有编译时检查。在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 2.2.3的文档中,有一个很好的章节讨论了支持类型化消息发送和响应的困难
罗兰·库恩(Roland Kuhn)在《Akka类型化频道:将类型计算实现为宏》(/)上的一篇很好的NEScala演讲》中讨论了类型化频道的实现。感谢您提供了有用的答案。您(akka团队)是否曾经尝试过向参与者的消息添加类型约束,或者这从来没有被认为是一个有用的想法?在过去的列表中已经有关于它的讨论,但我们总是在同一个地方结束,TypedActor用于那个用例,而参与者用于整个动态行为。如果你想感觉自己更能掌控局面,你可以在ActorRef上尝试你自己的抽象。这有用吗?干杯√类型化频道已被删除。“类型化通道是我们决定删除的一项实验性功能:它的实现依赖于Scala的一项实验性功能,Java和其他语言对此没有对应关系,而且它的使用也不直观。”
val inputMessage = Signal(FooInput, Foo)
actor ! inputMessage