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

Time:02-28

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 vars, 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.

  • Related