scala - 在 Scala 中添加和删除回调

标签 scala

这更多是一个“风格”问题......但它可能很有趣。

我写了以下特征:

trait EventProducer[B] {

  private var listeners: List[B => Unit] = List()

  def addListener(newListener: B => Unit) {
    listeners = listeners :+ newListener
  }

  protected def fireEvent(event: B) {
    listeners.map(listener => {
      listener(event)
    })
  }
}

到目前为止一切顺利。现在我想添加一个removeListener 函数...但是,嘿,我该怎么做呢?在 Java 中这很容易,因为我不使用匿名函数,而是使用一个类,然后我可以按值在列表中找到它并将其删除。但在这里我没有引用该函数(除非我保留它并且它不实用)。那么实现这个的好方法是什么?

最佳答案

看看我的微图书馆Model 。正如 @sschaef 指出的,您需要保留对该函数的引用。所以我从 addListener 返回它(简化):

class Model[U] {
  type Listener = PartialFunction[U, Unit]

  private var listeners = Vector.empty[Listener]

  def addListener(pf: Listener): pf.type = {
    listeners :+= pf
    pf
  }

  def removeListener(pf: Listener): Unit = {
    val idx = listeners.indexOf(pf)
    if (idx >=0) {
      listeners = listeners.patch(idx, Nil, 1)
    }
  }

  // ...
  def isEmpty = listeners.isEmpty
}

val m = new Model[String]
val l = m.addListener {
  case "handshake" => println("launch rockets")
}
m.removeListener(l)

需要非常小心的一件事是 eta 扩展,即使用方法代替函数。

def foo(s: String) = println(s"Observed $s")

m.addListener(foo)
m.removeListener(foo)
assert(m.isEmpty)  // fails!

这最后一点实际上无法编译,因为 eta 扩展仅适用于函数,而不适用于部分函数。在您的代码中,您使用了函数 B => Unit,因此请注意这个陷阱。

关于scala - 在 Scala 中添加和删除回调,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20588290/

相关文章:

algorithm - 将前 10% 的未排序 RDD 作为 Spark 中的另一个 RDD 返回的有效方法?

java - 如何将 JFROG 工件添加到 sbt.build 文件中?

java - JTable 中的 JProgressBar 未更新

shell - 如何在scala中编写支持readline的交互式shell?

scala:私有(private)实用方法应该存在于伴随对象中吗?

java - Scala Spring Boot Autowiring 不起作用

scala - 如何在 sbt 0.13 中使用 sbt-scalabuff 插件?

java - 在 Java 中使用 Scala Function2 对象

用于选项的 Scala Monoid 组合器

scala - 如何在 Scala 中使用具有多个输入的隐式?