How to use stackable trait pattern with Akka actors?
akka, scala, traits
Solution
There's a simple and concise solution:
Define a Receiving trait that chains multiple receive functions using `orElse` :
trait Receiving {
var receivers: Receive = Actor.emptyBehavior
def receiver(next: Actor.Receive) { receivers = receivers orElse next }
def receive = receivers // Actor.receive definition
}
Using this in actors is easy:
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 */
}
}
First PubSubActor's receive will be called. If message wasn't handled it will be passed to MyActor's receive.
Problem
I'm trying to implement a Pub/Sub trait to mix into other akka actors using a stackable trait. Here is what I came up with: ``` 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) => /* ... */ } } ``` At which point, the compiler throws back an error: error: overriding method receive in trait MyActor... method receive needs `abstract override' modifiers. Can you explain to me why this isn't working? How can I fix it so it works? Thanks! UPDATE The following works: ``` 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 ``` But why? Why can I get the behavior I want this way but not the other? Any reasons? I can't seem to figure out the underlying difference between these two samples that makes the difference.