Skip to content

Instantly share code, notes, and snippets.

@maiha
Created August 11, 2011 18:12
Show Gist options
  • Save maiha/1140325 to your computer and use it in GitHub Desktop.
Save maiha/1140325 to your computer and use it in GitHub Desktop.
overloaded receive in akka
// Why not define actor receive methods with overload?
//
// [features]
// * simple: there are only receiver's codes
// * readability: logic is defined just like receive(aMessage)
// * extensibility: add new receive logic (no needs to care receive matcher)
// * scalability: works well with traits and inheritances
// [restrictions]
// * all messages should be case classes (case objects cannot be used)
// [traditional way]
class Foo extends Actor {
def doXXX(m:XXX)
...
def doYYY(m:YYY)
...
def receive = {
case m:XXX => doXXX(m)
case m:YYY => doYYY(m)
// [overloaded way]
class Foo extends Actor with Overload {
def receive(m:XXX)
...
def receive(m:YYY)
...
// Wow, simple!!
package akka.actor
trait Overload { this:Actor =>
protected lazy val receiveHandlers = {
val map = Map[Class[_], java.lang.reflect.Method]()
val methods = getClass.getMethods.filter(m => m.getName == "receive" && m.getParameterTypes.size == 1)
methods.foldLeft(map){(m,i) => m + (i.getParameterTypes.head->i)}
}
protected def receive:PartialFunction[Any, Unit] = {
case m:Object if receiveHandlers.contains(m.getClass) =>
receiveHandlers(m.getClass).invoke(this, m)
}
}
import akka.actor.{Actor, Overload}
import Actor._
case object Start
case object Stop
case class Time(msec:Long)
class StopWatch extends Actor {
var startedAt: Long = 0L
def doStart {
startedAt = now
}
def doStop {
self reply Time(now - startedAt)
}
def receive = {
case Start => doStart
case Stop => doStop
}
protected def now = java.util.Calendar.getInstance.getTime.getTime
}
watch = actorOf(new StopWatch).start
watch ! Start
println(watch !! Stop)
import akka.actor.{Actor, Overload}
import Actor._
// all messages should be case classes to be used in overloading
case class Start()
case class Stop()
case class Time(msec:Long)
class StopWatch extends Actor with Overload {
var startedAt: Long = 0L
def receive(m:Start) {
startedAt = now
}
def receive(m:Stop) {
self reply Time(now - startedAt)
}
protected def now = java.util.Calendar.getInstance.getTime.getTime
}
val watch = actorOf(new StopWatch).start
watch ! Start()
println(watch !! Stop())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment