akka/akka — pull request #449 by havocp (2012-05-14 00:17:05+00:00)
Title: add Actor.aroundReceive to support mixin traits

An idea for you - this patch adds only one line of non-test non-comment code, and enables message-handling mixins without requiring the subclass to be modified. It also cleanly supports multiple mixins to one concrete class.

Use cases:
- A web socket actor base class was one real-world case I was wanting this
- There was also an example in the docs already, this patch adjusts it so see the patch
- In googling around for a solution I found someone else asking for it here: http://scala-forum.org/read.php?3,234,234#msg-234
- A possible example use in akka itself would be to implement `trait Router` without needing a special `routerReceive` method

The test suite patch shows the usage, but here's one inline. Before (in Akka 2.0):

```scala
trait WebSocketActor extends Actor {
// defensive "final" to avoid silently breaking,
// also prevents mixing in multiple traits
final def receive = {
case WebSocketMessage(whatever) =>
} orElse subReceive
protected def subReceive: Receive
}

class ConcreteActorWithWebSocketSupport extends WebSocketActor {
// subclass must switch from receive to subReceive
override def subReceive = {
case whatever =>
}
}
```

In the above pattern, each mixin has to invent its own convention for how to subtype, and to use a mixin you have to redo the subtype slightly. With `aroundReceive` these issues are cured:

```scala
trait WebSocketActor extends Actor {
// no need to invent a special method name or mess with receive
def aroundReceive = {
case WebSocketMessage(whatever) =>
} orElse super.aroundReceive
}

// now to mixin, just s/Actor/WebSocketActor/, no rewriting
class ConcreteActorWithWebSocketSupport extends WebSocketActor {
// just use regular receive
override def receive = {
case whatever =>
}
}
```

No boilerplate in the concrete subclass - the complexity moves from an app class like ConcreteActorWithWebSocketSupport to a library class like WebSocketActor.

The `aroundReceive` pattern allows one concrete subclass to mixin multiple base classes; only one trait can be mixed in if mixins are using a pattern like the current `trait Router` which does a `final def receive`.