2010-03-09 20 views
8

Ho implementato un tratto Ascolto/Ascolto che può essere aggiunto agli attori. Mi chiedo se sia possibile attribuire questo stile di tratto a un attore senza che debba chiamare esplicitamente il metodo listenerHandler?Compositore

Inoltre, mi aspettavo di trovare questa funzionalità nella libreria di Akka. Mi sto perdendo qualcosa o c'è qualche ragione 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()) 
    } 
} 

risposta

5

perché non estendere Actor direttamente, o se si vuole non-attori da Listenable anche, creare un ListenableActor che si estende Attore con Listenable?

In questo caso, in Attore si sostituisce l'receive come in precedenza (eccetto che si desidera chiamare anche super.receive, si desidera semplicemente modificare la funzione passata).

+0

Beh, questa è la cosa, in entrambe le situazioni avrei dovuto ricordarsi di chiamare eit il suo super.receive o * listenerHanlder *. Mi chiedevo se esistesse un meccanismo in Scala in generale o in una qualsiasi delle librerie di attori che permettesse all'attore di implementare Listenable di non dover fare nulla se non dire: * con Listenable * –

+0

Ma dovresti solo dire "estende ListenableActor". invece di "estende l'attore"; all'interno di 'ListenableActor' avresti già sovrascritto' receive' (e, presumibilmente, 'receiveWithin'). Vedi anche la risposta di Daniele. –

2

Suggerisco di estendere Actor e utilizzare un abstract override.

0

Ecco una soluzione (una versione modificata dell'esempio da 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) 
     } 
    } 
} 
+0

Hai appena cambiato un 'tratto' in un' class' ... –

Problemi correlati