你能否解释一下为什么第二次调用listen方法不起作用并提出一个解决方案让它工作?
object Example extends App {
case class Event(kind: Int)
trait Listener { def handle(e: Event) }
val listeners = scala.collection.mutable.Map[Int, Listener]()
def emit(e: Event) = listeners.get(e.kind).foreach(_.handle(e))
def listen(kind: Int)(f: (Event) => Unit) {
val l = new Listener() { override def handle(e: Event) = f(e) }
listeners += kind -> l
}
implicit def unit2EventUnit(f: => Unit) = (e: Event) => f
// This works as expected
println("1")
listen(1) { e: Event => println("a"); println("b") }
println("2")
emit(new Event(1))
println("3")
// Why this does not work? "c" should appear between "4" and "d", not "3" and "4"
listen(2) { println("c"); println("d") }
println("4")
emit(new Event(2))
println("5")
}
我知道这会奏效:
implicit def unit2EventUnit2(f: () => Unit) = (e: Event) => f()
listen(2) { () => println("c"); println("d") }
但这样写起来会更简单:
listen(2) { println("c"); println("d") }
答案 0 :(得分:3)
编译器只能在listen(2) { () => println("c"); println("d") }
中看到一个块。但是,此块与listen函数的签名不匹配,但它返回Unit
并且存在从Unit
到Event => Unit
的隐式转换,因此它采用块中的最后一个表达式并应用转换。这就是你得到这个结果的原因。我没有看到明显的解决方案,但您可以忽略函数中的参数并将其写为
listen(2) { _ => println("c"); println("d") }
然后你也不需要隐式转换。无论如何都不应该使用这种转换,因为它们使您的代码难以为不知道转换的人提供理由,并且它可能是意外行为的来源。