I want an object to have a boolean property that returns true when I first get it, and the false, in a second time I get it. This must repeat every time I call it (if it is an even call, returns true; if it's an odd call, returns false).
I know I can achieve this in a class property like this:
class Foo {
var bar: Boolean = true
get() {
val value = field
bar = value.not()
return value
}
private set
}
Test this snippet at: kotlinlang Playground
However, an extension property can't be implemented in the same way, like this:
var Foo.bar: Boolean = true // I get the first error here
get() {
val value = field // I get the second error here
bar = value.not()
return value
}
private set
Because I get two erros:
extension property cannot be initialized because it has no backing field
Unresolved reference field
Is it possible to achieve what I want with kotlin?
BTW, I'm using the version 1.8.0 of the kotlin library on Android.
To achieve this, you need to store the state somewhere. You could do so in a global map, as shown by @broot. See their excellent answer for some more details on why a global map might not be a good idea.
Implementation wise though, it might be nicer to hide the map in a property class:
fun main() {
val one = Foo()
val two = Foo()
println(one.bar) // false
println(two.bar) // false
println(one.bar) // true
println(one.bar) // false
println(two.bar) // true
println(one.bar) // true
}
class Foo
val Foo.bar by Alternate()
class Alternate {
private val values = mutableMapOf<Foo, Boolean>()
operator fun getValue(foo: Foo, p: KProperty<*>): Boolean {
val previous = values[foo] ?: true
values[foo] = !previous
return !previous
}
}