In most examples of proper usage of the scala (and akka) actor frameworks, people tend to derive every message from a single trait. For example:
trait Message
object Ping extends Message
object Pong extends Message
However, in both Scala and Akka, message reception is not typed at all. Is there any reason to implement a common trait ?
This really depends on what you are trying to achieve. For example, I recently built a small application using actors which had several types of actors, and a managing actor which acted more or less like a router. Now, the working actors could receive lots of different messages, for example Foo
, Bar
and Baz
. Without a Supertype, in the managing actor I'd have to write something like this:
react {
case x:Foo | x:Bar | x:Baz => worker ! x
}
Which is obviously unnecessarily verbose. So in this case, a supertype WorkerMessage
would make a lot of sense, because it simplifies your code:
react {
case x:WorkerMessage => worker ! x
}
On the other hand, this makes the messages Foo
, Bar
and Baz
pretty much unusable for any other purpose than being used by your WorkerActors. If you had a message Stop
or Init
for example, this would probably be bad because you'd need to redefine it all over the place.
So if you know you'll only have actors which do not pass messages around (that is, they process them by themselves), then I guess you'll be just fine without a supertype for them.
I guess the reason that people do this more or less by default is that if you later change your code you don't have to create the trait afterwards, because you already did in the beginning.
Personally, I always try to avoid unnecessary overhead, so I'd probably not define a supertype unless I really need it. Also, I really don't know if creating a supertype has any effect on performance at all, but I'd be interesting to know.
Both with scala.actors
(via InputChannel[T]
or Reactor[T]
) and Akka (TypedActor
) you can set type bounds for the incoming messages;
In the most examples, messages extend a sealed trait
. That's done for 2 reasons:
if the message handler (partial function) of your actor doesn't cover all the messages that extend the trait, compiler generates a warning;
sealed trait
can be extended only in the source file, where the trait is defined, and, thus, client cannot define it's own messages that extend the trait;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With