我注意到编写此scala
代码是合法的:
val fussyActor = actor {
loop {
receive {
case s: String => println("I got a String: " + s)
case _ => println("I have no idea what I just got.")
}
}
}
我从文档中了解到actor
是一个特征,其中包含loop
和receive
个值成员。但是如何像上面那样堆叠这些方法呢?它是在实施还是重写这些方法?我对这种语法很困惑。请提供一些很好的参考/指示。
答案 0 :(得分:5)
首先,标准免责声明。 Scala Actors已被弃用,赞成Akka Actors。如果你想继续学习使用Scala的Actors,你应该研究Akka而不是研究Scala Actors。
现在,关于你的问题。这里有几件事情,所以让我们首先介绍一下你需要做些什么来定义一个新的Scala Actor。如果查看Scala Actor特征,您会发现有一个必须提供的抽象方法称为act():Unit
。这是一种不接受任何输入并且不返回任何输入的方法。它定义了actor的行为。因此,在最简单的形式中,自定义Scala Actor可以是:
class MyActor extends Actor{
def act(){
}
}
现在这不是一个非常有趣的演员,因为它什么都不做。现在,提供行为的一种方法是调用receive
方法,提供PartialFunction[Any,R]
,其中R是泛型返回类型。你可以这样做:
class MyActor extends Actor{
def act(){
receive{
case "foo" => println("bar")
}
}
}
所以现在如果这个演员收到消息“foo”,它将打印“bar”。这里的问题是,这只会发生在第一条消息上,然后才会发生。解决这个问题。我们可以通过拨打receive
来打电话给loop
,以便继续为收到的每条消息执行receive
次呼叫:
class MyActor extends Actor{
def act(){
loop{
receive{
case "foo" => println("bar")
}
}
}
}
所以现在开始看起来像你的例子了。我们正在利用loop
特征附带的receive
和Actor
方法来为此演员提供行为。最后,我可以使用actor
伴随对象上的Actor
方法动态定义一个显式类,而不是将显式类定义为我的actor。该方法采用一个函数体,将用作act
impl,如下所示:
def actor(body: => Unit){
val a = new Actor {
def act() = body
override final val scheduler: IScheduler = parentScheduler
}
}
因此,在您的示例中,您正在动态创建一个新的actor实现,并为act
提供一个impl,它将循环并使用您为消息处理提供的部分函数不断调用receive
。 / p>
希望这能澄清一些事情。您“覆盖”(提供impl)的唯一方法是act
。当您看到loop
和receive
时,这些不是覆盖;它们只是调用Actor
特征上的现有方法。
答案 1 :(得分:1)
实际上没有import Actor._
是违法的。
没有导入的代码:
val fussyActor = Actor.actor {
Actor.loop {
Actor.receive { ... }
}
}
actor
,loop
和receive
是对象Actor
的方法。
def actor(body: ⇒ Unit): Actor
def loop(body: ⇒ Unit): Unit
def receive[A](f: PartialFunction[Any, A]): A
方法actor
接受by-name
Untit
参数body
- 在单独的线程中执行的一些代码块,并使用Actor
方法创建act
使用参数body
实现。
方法loop
接受by-name
Untit
参数body
- 某些代码块在无限循环中执行。
方法receive
接受PartialFunction
作为参数f
,并使用message作为参数调用f
。它接收来自与当前线程关联的actor的消息。
请注意,不推荐使用scala actor,您应该使用akka actors。请参阅The Scala Actors Migration Guide。