Created
August 11, 2011 18:12
-
-
Save maiha/1140325 to your computer and use it in GitHub Desktop.
overloaded receive in akka
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // 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!! |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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