2010-03-09 8 views
8

Я реализовал признак Listenable/Listener, который можно добавить в Актеры. Мне интересно, можно ли прикрепить этот стиль признака к актеру без необходимости явного вызова метода listenHandler?Композиционные актеры

Также я ожидал найти эту функциональность в библиотеке Akka. Я что-то упустил или есть какая-то причина, по которой Акка не включил бы это?

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()) 
    } 
} 

ответ

5

Почему бы не расширить Actor напрямую, или если вы хотите не-актеров быть Listenable также создать ListenableActor, расширяющий актер с Listenable?

Вы тогда переопределили бы receive в Актере, как вы уже это делали (кроме того, что вы хотите также позвонить super.receive, - вы просто хотите изменить переданную функцию).

+0

Ну это дело, в обоих случаях я должен помнить, чтобы позвонить еи ее super.receive или * listenerHanlder *. Мне было интересно, существует ли какой-либо механизм в Scala вообще или в любой из библиотек Actor, позволяющий актеру, реализующему Listenable, не делать ничего, кроме как сказать: * с Listenable * –

+0

Но вам нужно было бы только сказать 'extends ListenableActor' вместо 'extends Actor'; внутри 'ListenableActor' вы бы уже переопределили' receive' (и, предположительно, 'receiveWithin'). См. Также ответ Даниила. –

2

Предлагаю вам продлить действие Актера и использовать abstract override.

0

Вот решение (модифицированная версия примера от начала 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

Вы просто изменили 'trait' на' class' ... –