在 Kotlin 中,是否可以更改闭包中的引用?

问题描述 投票:0回答:1

这个想法是,您将 lambda 传递给一个类,并且您希望在将 lambda 传递给该类后更改实现,但该类没有公开任何更新 lambda 实现的方法。

据我了解,lambda 在实例化时捕获对原始实现的引用,并且无法更新该引用。

此时,您是否被迫使用新的实现重新创建类?

kotlin lambda closures
1个回答
0
投票

我们无法替换已经传递给任何函数或对象的值或引用:

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 不会改变,但它引用了我们可以修改的局部变量。

© www.soinside.com 2019 - 2024. All rights reserved.