score:1
For the first, excuse me for my English I think the point is that abstract override modifier requires presence of concrete implementation of receive method but in the first construction
class MyActor extends Actor with PubSubActor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}}
it is not done
The reason is that scala compiler makes linearization for inheritance so in receive's method chain we have the following sequence:
1) override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
2) abstract override def receive = super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
3) then Actor.receive - it hasn't an implementation
So PubSubActor.receive cannot be called because it use super.receive, in its turn super.receive relies on Actor.receive, but Actor.receive hasn't an implementation.
In the second construction
class MyActor extends Actor {
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}}
class MyActorImpl extends MyActor with PubSubActor
we have receive's method chain
1)
abstract override def receive = super.receive orElse {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
2)
override def receive = {
case SomeMessage(a, b, c) => /* ... */
}
3) then Actor.receive - it hasn't an implementation
So PubSubActor.receive can successfully call super.receive
Additional info:
score:2
Try it the other way around:
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
}
}
Note that this still makes use of the stackable trait pattern, which is hidden by the fact that I've omitted the core. So something like this would still work (at least I think I will, ATM I have no time to check if it compiles).
class Core extends Actor {
def receive = Actor.emptyBehavior
}
class MyActor extends Core with Subscription
BTW, you can read more about the pattern (not related to Actors) here.
score:9
You can certainly achieve what you are looking for using Akka's composable actor feature. This is described a bit in Extending Actors using PartialFunction chaining.
First, the infrastructure code (straight from the docs):
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()
}
Then the behaviors you want to be able to compose into actors:
trait PubSubActor { self:ComposableActor =>
receiveBuilder += {
case Subscribe(topic) => /* ... */
case Publish(topic, msg) => /* ... */
}
}
trait MyActor { self:ComposableActor =>
receiveBuilder += {
case SomeMessage(a, b, c) => /* ... */
}
}
And lastly, an actual actor that uses these composable behaviors:
class MyActorImpl extends ComposableActor with PubSubActor with MyActor
score:17
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.
Source: stackoverflow.com
Related Query
- How to use stackable trait pattern with Akka actors?
- How to use scala trait with `self` reference?
- How to use an Akka Streams SourceQueue with PlayFramework
- How to use mocks with the Cake Pattern
- Can the stackable trait pattern be used with singleton objects?
- How to use Tinkerpop with actors
- How to respond to an Ask pattern with a failure using Akka TestKit?
- Scala How to use pattern matching with a non generic LazyList?
- In scala, how can I use pattern match to match a list with specified length?
- How to use star pattern with unapplySeq in Scala?
- How to use the Akka ask pattern without blocking
- How do I use builder pattern to return inner object with Scala macros
- How to use futures with Akka for asynchronous results
- How do I use pattern matching with parametrized traits?
- How to use pattern matching with regular expressions
- In Scala, how to use unapplySeq with pattern matching like List, start pattern and varargs parameters?
- How to use circe with generic case class that extends a sealed trait
- How to deal with HKT types in a pattern matching when you use 'type' keyword to create them?
- How to properly use akka actors in scala
- How to use pattern matching with function values in Scala
- how to integrate akka actors with decline
- Scala how to use akka actors to handle a timing out operation efficiently
- How to I register Akka Typed actors to Receptionist with dynamic keys?
- How to use the Akka sample cluster kubernetes with Scala and minikube?
- scala how to use pattern matching with inheriance and templated class
- How to find source of unexpected message in Akka actors with Scala
- How to resolve - method using in object WebSocket is deprecated: Use accept with an Akka streams flow instead
- How to use Typesafe Akka with Node.js
- Akka HTTP: How to split routes with actors
- How to use Akka actors to handle HTTP requests in Akka
More Query from same tag
- Trying to make use of Jcrop and serverside image resizing with scala Scrimage lib
- Map with different types to String
- Scala/Spark: How to print content of a dataset[row] when row consists of fields of type double
- bad symbolic reference on SQLContext.class in Eclipse Luna scala IDE
- Scala - How to stop a futures executed with a akka scheduler
- Scala: Is my `equals` method correct?
- How can I import a scala class into another using gatling?
- Reading Spring Boot ConfigurationProperties with Scala
- Keep main thread running while await classes haven't finished
- How to reduce a compact buffer in scala?
- How do you use RxScala in Intellij Idea 14?
- Scala http client for large files
- range lock in java
- Is it possible to get intellij to print out variables/expressions to the console at a breakpoint?
- Scala Map -> Reduce vs. FoldRight
- Getting max value out of a dataframe column of timestamp in scala/spark
- Scala: exception handling in anonymous function
- What is the equivalent to --cacerts in Scala or Java?
- Sort list of tuple in descending order with category alternating condition
- Does IDEA recognize Play Scala template changes?
- Making key value pairs from an HDFS sequence file using Apache Spark
- Upper and lower of a passed value in a scala Array
- Applying function to Spark Dataframe Column
- Spark reparition() function increases number of tasks per executor, how to increase number of executor
- How to define new primitive data type and its behavior in Scala
- How can I deserialize from JSON with Scala using *non-case* classes?
- Gatling compatibility issue with Scala 2.13.0 in IntelliJ
- How to "map" an array to a single new object?
- How to read from embedded-kafka with fs2-kafka
- How to sum the corresponding values in the List into a Tuple?