如何为观察者系统创建这种接口?

发布于 2024-10-31 02:06:34 字数 303 浏览 0 评论 0原文

addListener[FooEvent] { e => println("Got a FooEvent") }
dispatchEvent(new FooEvent())

这可能吗?我需要能够将 addListener 方法中的类型参数转换为字符串并将侦听器存储在映射(eventtype -> 函数)或其他内容中。然后,对于dispatchEvent,我需要确定参数的字符串类型以检索该事件的侦听器。

我不确定实现,但我真的很想使用这种接口,而不必为可观察对象上的每个事件类型声明 2 个方法。有什么想法吗?

addListener[FooEvent] { e => println("Got a FooEvent") }
dispatchEvent(new FooEvent())

Is this even possible? I'd need to be able to convert the type parameter in the addListener method to a string and store the listeners in a map (eventtype -> function) or something. Then for dispatchEvent I'd need to determine the string type for the parameter to retrieve the listeners for that event.

I'm unsure of the implementation but I'd really like to use this kind of interface instead of having to declare 2 methods for each event type on an observable object. Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

幻想少年梦 2024-11-07 02:06:34

是的,这是可能的,而且非常简单。但您必须记住,如果您想再次从侦听器中将其删除,则需要保留传入函数的引用。您可以做的是这样的:

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)

如果您想将事件类型作为类型提供参数,您必须另外采用隐式 ManifestClassManifest 参数:

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

Yes it is possible and quite straight forward. You have to remember though, that you need to hold on to the reference of a function you pass in if you want to remove it from the listeners again. What you could do is something like this:

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 returns the function so you can store it in val for removing it later:

val listener = foo.addListener { e => println(e) }
foo.dispatchEvent(FooEvent(3))
foo.removeListener(listener)

If you want to supply the event type as a type parameter you have to additionally take an implicit Manifest or ClassManifest parameter:

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
}

And using it:

addListener[FooEvent] { e => println(e.x) }
dispatch(FooEvent(3))
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文