use*_*159 19 scala traits akka
我正在尝试使用可堆叠特征将Pub/Sub特性混合到其他akka actor中.
这是我想出的:
trait PubSubActor extends Actor {
abstract override def receive =
super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
class MyActor extends Actor with PubSubActor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
}
Run Code Online (Sandbox Code Playgroud)
此时,编译器会抛出一个错误:错误:重写方法在特征中接收MyActor ...方法接收需要`abstract override'修饰符.
你能解释一下为什么这不起作用吗?我怎样才能修复它以便它有效?
谢谢!
UPDATE
以下作品:
trait PubSubActor extends Actor {
abstract override def receive =
super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
class MyActor extends Actor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
}
class MyActorImpl extends MyActor with PubSubActor
Run Code Online (Sandbox Code Playgroud)
但为什么?为什么我能以这种方式获得我想要的行为而不是另一种?有什么原因?我似乎无法弄清楚这两个样本之间的根本区别是什么.
And*_*ejs 17
有一个简单而简洁的解决方案:
定义使用orElse以下链接多个接收函数的接收特征:
trait Receiving {
var receivers: Receive = Actor.emptyBehavior
def receiver(next: Actor.Receive) { receivers = receivers orElse next }
def receive = receivers // Actor.receive definition
}
Run Code Online (Sandbox Code Playgroud)
在演员中使用它很容易:
trait PubSubActor extends Receiving {
receiver {
case Publish => /* I'm the first to handle messages */
}
}
class MyActor extends PubSubActor with Receiving {
receiver {
case SomeMessage => /* PubSubActor didn't handle, I receive the message */
}
}
Run Code Online (Sandbox Code Playgroud)
将调用第一个PubSubActor的接收.如果没有处理消息,它将被传递给MyActor的接收.
使用Akka的可组合演员功能,你当然可以实现你想要的.这在使用PartialFunction链接扩展Actor中有所描述.
首先,基础设施代码(直接来自文档):
class PartialFunctionBuilder[A, B] {
import scala.collection.immutable.Vector
// Abbreviate to make code fit
type PF = PartialFunction[A, B]
private var pfsOption: Option[Vector[PF]] = Some(Vector.empty)
private def mapPfs[C](f: Vector[PF] => (Option[Vector[PF]], C)): C = {
pfsOption.fold(throw new IllegalStateException("Already built"))(f) match {
case (newPfsOption, result) => {
pfsOption = newPfsOption
result
}
}
}
def +=(pf: PF): Unit =
mapPfs { case pfs => (Some(pfs :+ pf), ()) }
def result(): PF =
mapPfs { case pfs => (None, pfs.foldLeft[PF](Map.empty) { _ orElse _ }) }
}
trait ComposableActor extends Actor {
protected lazy val receiveBuilder = new PartialFunctionBuilder[Any, Unit]
final def receive = receiveBuilder.result()
}
Run Code Online (Sandbox Code Playgroud)
然后你想要能够组成演员的行为:
trait PubSubActor { self:ComposableActor =>
receiveBuilder += {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
trait MyActor { self:ComposableActor =>
receiveBuilder += {
case SomeMessage(a, b, c) => /* ... */
}
}
Run Code Online (Sandbox Code Playgroud)
最后,一个使用这些可组合行为的实际actor:
class MyActorImpl extends ComposableActor with PubSubActor with MyActor
Run Code Online (Sandbox Code Playgroud)
换个方式试试:
object Subscription {
case object Subscribe
case object Unsubscribe
}
trait Subscription {
this: Actor =>
import Subscription._
var subscribers = Set.empty[ActorRef]
def receive: Receive = {
case Subscribe => subscribers += sender
case Unsubscribe => subscribers -= sender
}
}
class MyActor extends Actor with Subscription {
def receive = super.receive orElse {
case msg => // handle msg
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,这仍然使用可堆叠特征模式,该模式由于我省略了核心而被隐藏。所以这样的东西仍然可以工作(至少我认为我会,ATM我没有时间检查它是否编译)。
class Core extends Actor {
def receive = Actor.emptyBehavior
}
class MyActor extends Core with Subscription
Run Code Online (Sandbox Code Playgroud)
顺便说一句,您可以在此处阅读有关该模式(与 Actor 无关)的更多信息。
| 归档时间: |
|
| 查看次数: |
6507 次 |
| 最近记录: |