是否可以在 Kotlin 的泛型函​​数末尾将 T 或 'this' 设为 null?

Is it possible to null T or 'this' at the end of generic function for Kotlin?

我的项目中有一个监听器。它被分配给 drawerLayout。我想在 lambda 函数中删除它并立即(按顺序)将其置空。是否可以在泛型函数的末尾使 T 或 this 为空。

这是我的代码:

// Usage
actionBarListener?.let {
   drawerLayout.removeDrawerListener(it) // remove listener
   actionBarListener = null // null it
}

// Usage expected
actionBarListener.releaseAndSetNull {
   drawerLayout.removeDrawerListener(it) // remove listener and null it
}

// Generic
fun <T> T?.releaseAndSetNull(block: (T?) -> Unit) = apply {
    this?.apply { block.invoke(this) }
    this = null // Error: variable expected
}

我能想到这永远行不通的几个原因。

首先,通用函数不知道 thisvar 还是 val。而且此功能仅适用于 var

同样,它不知道它是否可以为空,这也是一个要求。

此外,甚至可能不是调用函数的变量。

就像说你有

fun getActionBarListener() {
    return actionBarListener
}

然后你可以在其他地方做

getActionBarListener().releaseAndSetNull {
   drawerLayout.removeDrawerListener(it) // remove listener and null it
}

您认为它会如何运作?

甚至匿名对象也可以调用此函数。

正如 Ivo Beckers 所说,此功能仅适用于 var,即 KMutableProperty0<T>。所以你可以KMutableProperty0<T?>上写一个扩展,然后用反射来设置,如果你不介意用反射,那就是。

inline fun <T: Any> KMutableProperty0<T?>.releaseAndSetNull(block: (T?) -> Unit) {
    block(this.get())
    this.set(null)
}

// or if you don't want the block to be called if the property is null:

inline fun <T: Any> KMutableProperty0<T?>.releaseAndSetNull(block: (T) -> Unit) {
    this.get()?.run(block)
    this.set(null)
}

那么假设你有一个 属性:

var foo: Int? = 10

你可以这样做:

::foo.releaseAndSetNull { println("Foo: $it") }
// or if foo belongs to someObject
someObject::foo.releaseAndSetNull { println("Foo: $it") }

查看生成的字节码,其实现方式(可能会发生变化)是 属性 以这种方式引用的每个唯一 属性 都会导致内部 class 生成。内部 class 将具有 getset 方法,这些方法只需很少的额外成本即可完成工作 - 因为它们可以直接设置正确的 属性 。所以真正的主要成本是生成的额外内部 class。