Pregunta
He implementado un rasgo de escucha/oyente que se puede agregar a los actores. Me pregunto si es posible adjuntar este estilo de rasgo a un actor sin que tenga que llamar explícitamente al dueño ¿método?
También esperaba encontrar esta funcionalidad en la Biblioteca Akka. ¿Me estoy perdiendo algo o hay alguna razón por la que Akka no incluye esto?
trait Listenable { this: Actor =>
private var listeners: List[Actor] = Nil
protected def listenerHandler: PartialFunction[Any, Unit] = {
case AddListener(who) => listeners = who :: listeners
}
protected def notifyListeners(event: Any) = {
listeners.foreach(_.send(event))
}
}
class SomeActor extends Actor with Listenable
{
def receive = listenerHandler orElse {
case Start => notifyListeners(Started())
case Stop => notifyListeners(Stopped())
}
}
Solución
¿Por qué no extender Actor
Directamente, o si desea que los no sean escuchables también, cree un ListenAbleActor que extienda el actor con escucha?
Entonces anularías receive
en el actor como has hecho arriba (excepto que te gustaría llamar super.receive
Además, ¿no?
Otros consejos
Le sugiero que extienda el actor y use un abstract override
.
¿Por qué no he visto esta pregunta antes, Erm, bueno, mejor tarde que nunca?
Aquí hay una solución (una versión modificada del ejemplo desde el comienzo de Scala):
import se.scalablesolutions.akka.actor.Actor
case class AddListener(who: Actor)
case class RemoveListener(who: Actor)
class ListenableActor extends Actor {
private var listeners: List[Actor] = Nil
def receive = {
case AddListener(who) => listeners ::= who
case RemoveListener(who) => listeners.filter(_ ne who)
}
protected def notifyListeners(event: Any) = {
listeners.foreach(_.send(event))
}
}
class ImplementingActor extends ListenableActor {
override def receive = {
super.receive orElse {
case Message(content) => println(content)
}
}
}
Hay soporte incorporado para esto en Akka: https://github.com/jboner/akka/blob/release-1.2/akka-actor/src/main/scala/akka/routing/listeners.scala