是否可以在 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
}
我能想到这永远行不通的几个原因。
首先,通用函数不知道 this
是 var
还是 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 将具有 get
和 set
方法,这些方法只需很少的额外成本即可完成工作 - 因为它们可以直接设置正确的 属性 。所以真正的主要成本是生成的额外内部 class。
我的项目中有一个监听器。它被分配给 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
}
我能想到这永远行不通的几个原因。
首先,通用函数不知道 this
是 var
还是 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 将具有 get
和 set
方法,这些方法只需很少的额外成本即可完成工作 - 因为它们可以直接设置正确的 属性 。所以真正的主要成本是生成的额外内部 class。