I have in my project a listener. It is assigned to drawerLayout
. I would like to in lambda function remove it and null it at once (sequentially). Is it possible to null T or this
at the end of generic function.
Here is my code:
// 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
}
CodePudding user response:
As Ivo Beckers said, this function would only work on var
s, i.e. KMutableProperty0<T>
. So you could write an extension on KMutableProperty0<T?>
, and use reflection to set it, if you don't mind using reflection, that is.
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)
}
Then suppose you have a property:
var foo: Int? = 10
You can do:
::foo.releaseAndSetNull { println("Foo: $it") }
// or if foo belongs to someObject
someObject::foo.releaseAndSetNull { println("Foo: $it") }
Looking at the generated bytecode, the way this is implemented (which is subject to change) is that each unique property referred to by a property reference in this way causes an inner class to be generated. The inner class will then have get
and set
methods that do their jobs with little extra cost - as they can just set the right property directly. So really the main cost is the extra inner class that is generated.
CodePudding user response:
I can think of several reasons why this could never work.
First of, the generic function doesn't know if this
is a var
or val
. And this functionality could only works on a var
Likewise, it can't know if it's nullable, that's also a requirment.
Furthermore, it can even be the case that it's not a variable that's calling the function.
Like say you have
fun getActionBarListener() {
return actionBarListener
}
Then somewhere else you could do
getActionBarListener().releaseAndSetNull {
drawerLayout.removeDrawerListener(it) // remove listener and null it
}
How do you expect that to work?
Or even anonymous objects could call this function.