Reputation: 22512
I want to write extension function that modifies "this", for example:
var a = false
a.toggle() // now a contains false
or
var a = 1
a.increment() // now a contains 2
Is it possible in Kotlin?
I can create extension function that returns modified value, but leaves "this" unmodified, but I want even more convenience! It looks like Swift can do that.
Upvotes: 20
Views: 4352
Reputation: 31254
References to variables aren't supported yet but you can create extension functions to use with property references:
fun KMutableProperty0<Boolean>.not() = set(get().not())
fun KMutableProperty0<Int>.inc() = set(get().inc())
var a = false
var b = 1
fun main(vararg args: String) {
::a.not()
// now `a` contains `true`
::b.inc()
// now `b` contains `2`
}
Or if you'd rather the extension functions return the new value along with setting it:
fun KMutableProperty0<Boolean>.not(): Boolean = get().not().apply(setter)
fun KMutableProperty0<Int>.inc(): Int = get().inc().apply(setter)
Upvotes: 11
Reputation: 33839
As any other parameter of a function, this
is a reference to an object. On the other hand, var a
is a reference to the same object too. So basically you have two references that point to the same instance:
var a = false
val this = a // a.toggle()
There is no manipulation you can do to one of those references and change the other. They are unrelated variables with the same value, nothing more.
What you can do (in theory) is to make the object itself changeable:
class MutableBoolean(val value: Boolean)
val a = MutableBoolean(false)
a.toggle()
fun MutableBoolean.toggle() {value = !value}
Upvotes: 2
Reputation: 28056
You can not do this because it would require you to pass a
to the function by reference. This is not possible in Kotlin. All function arguments in Kotlin are passed by value.
However, you could simulate the behaviour using the following construct. It's not very convenient though.
fun Boolean.toggle(getter: () -> Boolean, setter: (Boolean) -> Unit) {
setter(!getter())
}
var a = false
println(a) // prints false
a.toggle({a}, {a = it})
// Or a.toggle(a::get, a::set), but that isn't supported (yet?)
println(a) // prints true
Upvotes: 2