سؤال
لقد قمت بتنفيذ سمة مستمعة / مستمع يمكن إضافتها إلى الجهات الفاعلة. أتساءل عما إذا كان من الممكن إرفاق هذا النمط من السمة إلى ممثل دون أن يتصل به صراحة listerhandler. طريقة؟
كما كنت أتوقع أن أجد هذه الوظيفة في مكتبة 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())
}
}
المحلول
لماذا لا تمديد Actor
مباشرة، أو إذا كنت تريد أن تكون الجهات الفاعلة غير قابلة للاستيلاء أيضا، فقم بإنشاء ListingableCtor الذي يمتد الممثل مع قابل للاستيلاء؟
ثم سوف تتجاوز receive
في الممثل كما فعلت أعلاه (إلا أنك تريد الاتصال super.receive
أيضا، أليس كذلك؟ - هل تريد فقط تعديل الوظيفة التي تمر في).
نصائح أخرى
أقترح عليك تمديد الممثل واستخدام abstract override
.
لماذا لم أر هذا السؤال من قبل، erm، حسنا، متأخرا أفضل من عدم:
هنا هو الحل (نسخة معدلة من المثال من بداية 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)
}
}
}
هناك دعم مدمج لهذا في Akka: https://github.com/jboner/akka/blob/release-1.2/akka-actor/src/main/scala/akka/routing/listeners.scala.