Да, это возможно и довольно прямо.Однако вы должны помнить, что вам нужно держаться за ссылку на функцию, которую вы передаете, если вы хотите снова удалить ее из слушателей.Вы можете сделать что-то вроде этого:
import collection.mutable.ArrayBuffer
val listeners = ArrayBuffer[FooEvent => Unit]()
def addListener(f: FooEvent => Unit) = {
listeners += f
f
}
def removeListener(f: FooEvent => Unit): Unit = {
listeners -= f
}
def dispatchEvent(e: FooEvent) = listeners.foreach(f => f(e))
addListener
возвращает функцию, чтобы вы могли сохранить ее в val
для последующего ее удаления:
val listener = foo.addListener { e => println(e) }
foo.dispatchEvent(FooEvent(3))
foo.removeListener(listener)
Если вы хотитечтобы предоставить тип события в качестве параметра типа, необходимо дополнительно принять неявный параметр Manifest
или ClassManifest
:
import collection.mutable.{ArrayBuffer, HashMap}
val listeners = HashMap[Class[Any],ArrayBuffer[Any]]()
def addListener[A](f: A => Unit)(implicit mf: ClassManifest[A]): A => Unit = {
listeners.getOrElseUpdate(mf.erasure.asInstanceOf[Class[Any]], ArrayBuffer[Any]()) += f
f
}
def dispatch[A](e: A)(implicit mf: ClassManifest[A]) =
for {
evListeners <- listeners.get(mf.erasure.asInstanceOf[Class[Any]])
listener <- evListeners
} listener.asInstanceOf[A => Unit] apply e
}
И использовать его:
addListener[FooEvent] { e => println(e.x) }
dispatch(FooEvent(3))