这个想法是,您将 lambda 传递给一个类,并且您希望在将 lambda 传递给该类后更改实现,但该类没有公开任何更新 lambda 实现的方法。
据我了解,lambda 在实例化时捕获对原始实现的引用,并且无法更新该引用。
此时,您是否被迫使用新的实现重新创建类?
我们无法替换已经传递给任何函数或对象的值或引用:
fun main() {
var handler = { println("Hello") }
val foo = Foo(handler)
foo.callHandler() // Hello
handler = { println("World") } // doesn't affect `foo`
foo.callHandler() // Hello
}
class Foo(private val handler: () -> Unit) {
fun callHandler() = handler()
}
但是,如果我们围绕接口设计代码,我们可以轻松提供一个仅委托给另一个实现的实现,并允许切换实现。在大多数情况下,lambda 是接口的实现:
fun main() {
val delegator = object : () -> Unit {
var handler = { println("Hello") }
override fun invoke() = handler()
}
val foo = Foo(delegator)
foo.callHandler() // Hello
delegator.handler = { println("World") }
foo.callHandler() // World
}
或者更简单:
fun main() {
var handler = { println("Hello") }
val foo = Foo { handler() }
foo.callHandler() // Hello
handler = { println("World") }
foo.callHandler() // World
}
请注意,传递的 lambda 不会改变,但它引用了我们可以修改的局部变量。