这更像是一个"风格"问题。。。但这可能很有趣。
我写了以下特点:
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中,这很容易,因为我不使用匿名函数,而是使用一个类,然后我可以按值在列表中找到它并将其删除。但这里我没有引用该函数(除非我保留它,而且它不实用)。那么,实现这一点的好方法是什么呢?
看看我的微库模型。正如@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
,因此要注意这个陷阱。