2010-03-09 11 views
8

Implementé un rasgo Listenable/Listener que se puede agregar a Actores. Me pregunto si es posible adjuntar este estilo de rasgo a un actor sin tener que llamar explícitamente al método listenerHandler?Composing actors

También esperaba encontrar esta funcionalidad en la biblioteca de Akka. ¿Me estoy perdiendo algo o hay alguna razón por la cual Akka no incluiría 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()) 
    } 
} 

Respuesta

5

por qué no extender Actor directamente, o si desea que no son actores sean Listenable también, crear un ListenableActor que se extiende Actor con Listenable?

Usted anularía receive en Actor como lo hizo anteriormente (excepto que también le gustaría llamar al super.receive, ¿no? - solo querría modificar la función que se transfirió).

+0

Pues esta es la cosa, en ambas situaciones que tendría que recordar llamar EIT su super.receive o * listenerHanlder *. Me preguntaba si había un mecanismo en Scala en general o cualquiera de las bibliotecas Actor que permitiera al actor que implementaba Listenable no tener que hacer nada excepto decir: * con Listenable * –

+0

Pero solo tendrías que decir 'extends ListenableActor' en lugar de 'extiende Actor'; dentro de 'ListenableActor' ya habrías anulado' receive' (y, presumiblemente, 'receiveWithin'). Ver también la respuesta de Daniel. –

2

Le sugiero que extienda Actor y use un abstract override.

0

Aquí es una solución (una versión modificada del ejemplo del Principio 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) 
     } 
    } 
} 
+0

Acabas de cambiar un 'rasgo' a una' clase' ... –

Cuestiones relacionadas