Question
J'ai implémenté un trait écoutable / auditeur qui peut être ajouté aux acteurs. Je me demande s'il est possible d'attacher ce style de trait à un acteur sans avoir à appeler explicitement le auditeur méthode?
Je m'attendais également à trouver cette fonctionnalité dans la bibliothèque Akka. Est-ce que je manque quelque chose ou y a-t-il une raison pour laquelle Akka ne l'inclure pas?
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())
}
}
La solution
Pourquoi ne pas s'étendre Actor
Directement, ou si vous voulez que les non-acteurs soient également écoutables, créez un écoute-écouter qui étend l'acteur avec écoutable?
Vous remplaceriez alors receive
en acteur comme vous l'avez fait ci-dessus (sauf que vous voudriez appeler super.receive
De plus, n'est-ce pas? - Vous voudriez simplement modifier la fonction qui est transmise).
Autres conseils
Je vous suggère d'étendre l'acteur et d'utiliser un abstract override
.
Pourquoi n'ai-je pas vu cette question auparavant, euh, eh bien, mieux vaut tard que jamais:
Voici une solution (une version modifiée de l'exemple du début 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)
}
}
}
Il y a une prise en charge intégrée pour cela à Akka: https://github.com/jboner/akka/blob/release-1.2/akka-actor/src/main/scala/akka/routing/isteners.scala