I want to replace
var timer = 100
//function called in an endless loop
fun update() {
timer --
println(timer)
}
with
var timer: Int by TimedVarDelegate(100)
//function called in an endless loop
fun update() {
println(timer)
}
Where the printed value is “100”, then “99”, etc…
The ‘update’ function is called every frames
Is it possible to create that “TimedVarDelegate” delegate ?
Do you want a delegate that just decrements the value every time it is accessed? If so, it’s possible:
import kotlin.reflect.*
class Delegate (start: Int) {
private var value: Int = start
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
return value--
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
this.value = value
}
}
fun main() {
val timer by Delegate(100)
println(timer)
// next frame
println(timer)
}
This delegate will not work however if you access the timer variable more than once per frame. You could however use something like this
import kotlin.reflect.*
class Delegate (start: Int) {
private var value: Int = start
operator fun getValue(thisRef: Any?, property: KProperty<*>): Int {
return value
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: Int) {
this.value = value
}
fun nextFrame() { value-- }
}
val timer by Delegate(100)
fun main() {
val timerDelegate = ::timer.getDelegate() as Delegate
println(timer)
timerDelegate.nextFrame() // next frame
println(timer)
}
It’s the behaviour of your second example that I want.
My program have a lot of these timers and the idea was to eliminate the need to write “aTimedVar --” every time I create a new var like this.
I believe your example works well but it doesn’t seem to make the code more concise though
Well if you have many of those timers you need to decrement at the end of each frame you can just create a list with their delegates and then do something like timerDelegates.forEach(::nextFrame)
.
But you won’t get around an implicit call for decrementing the values.
Maybe one advantage to the delegate approach is that you can pass a nextFrame
function to the delegate to create some custom changes, eg. increment one of the timers instead of decrementing or whatever you want to do. In that case you can also switch the delegate to be generic. Not sure if this is helpful in you current situation though.
Yes, making a list of timers would do the trick. Is there a way to not have to write “list.add(aTimedVar)” for each variables we have ?
If you are 100% sure that you will always update all timers at once you could put the list of timers in the companion object of the Delegate and then automatically add the timer to the list in the constructor
class TimerDelegate {
init {
allTimers.add(this)
}
// delegate functions ...
companion object {
private val allTimers = mutableListOf<TimerDelegate>()
fun updateAllTimers() = TODO()
}
}
1 Like
Seems good ! Can’t wait to try it out, thanks