Domanda
Ho implementato un tratto ascoltabile/ascoltatore che può essere aggiunto agli attori. Mi chiedo se è possibile attribuire questo stile di tratto a un attore senza che debba chiamare esplicitamente il ascoltatore metodo?
Inoltre mi aspettavo di trovare questa funzionalità nella biblioteca Akka. Mi manca qualcosa o c'è qualche motivo per cui Akka non lo includerebbe?
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())
}
}
Soluzione
Perché non estendersi Actor
Direttamente, o se vuoi che i non attori siano anche ascoltabili, crea un ascoltableactor che estende l'attore con ascoltabile?
Quindi sovrascriveresti receive
in attore come hai fatto sopra (tranne che vorresti chiamare super.receive
Inoltre, vero?-vorresti solo modificare la funzione che è passata).
Altri suggerimenti
Ti suggerisco di estendere l'attore e usare un abstract override
.
Perché non ho mai visto questa domanda prima, erm, beh, meglio tardi che mai:
Ecco una soluzione (una versione modificata dell'esempio dall'inizio 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)
}
}
}
C'è un supporto integrato per questo in Akka: https://github.com/jboner/akka/blob/release-1.2/akka-actor/src/main/scala/akka/routing/listeners.scala