https://kotlinlang.org logo
Title
b

bbaldino

03/19/2019, 8:25 PM
the goal is to get a 'cached' variable where the cache can be invalidated (and the variable should have its initializer re-run)
s

streetsofboston

03/19/2019, 8:27 PM
Why not make it a nullable
var
instead?
b

bbaldino

03/19/2019, 8:28 PM
pffft who wants to have to deal with null in kotlin? 🙂 plus i'd like to encapsulate the re-initialization logic
s

streetsofboston

03/19/2019, 8:28 PM
You can create a non-nullable (non lateinit) var, using a property Delegate.
b

bbaldino

03/19/2019, 8:29 PM
and, the field is not actually nullable, it's a view of a field from a buffer and the buffer can change, but re-parsing it every time would be costly, i only want to re-parse when something has changed
yeah i just wanted something a little cleaner than explicitly making a call to re assign it
s

streetsofboston

03/19/2019, 8:32 PM
This means it has certain behavior: Create/parse the value, return the cached value, clear the cached value. Why not make your own class called
Cached<T : Any>
that caches values of type
T
, creates/parses it when it is not cached and allows the value to be cleared (cache-clear)?
b

bbaldino

03/19/2019, 8:32 PM
yeah, that's the idea, i was just looking to do it as a delegate
ideally it'd be lazy as well
so there are some implementations to that i've found (in the links above), they're just a bit old...was just wondering if perhaps there was something cleaner now as they involve basically copying the
lazy
implementation and adding an
invalidate
s

streetsofboston

03/19/2019, 8:33 PM
That is possible: One part of the code will hold on to the property-delegate object, provide it to the class-instance that then uses this property-delegate. Then users of that class-instance can use the property as if it were a regular/plain property
But how would you call `invalidate`….?
b

bbaldino

03/19/2019, 8:34 PM
yeah, the implementations above save a reference to the delegate type, which sucks. and getting the delegate from the field also kinda sucks
but how does your solution change that? if the property still has it's type, then i'll have to cast/get the delegate to call invalidate, no?
i was actually planning on passing a prop reference to the delegate that serves as the dirty flag
so the class just sets the boolean to true, and the delegate can check it's current value
rather than having to get the delegate and call
invalidate
s

streetsofboston

03/19/2019, 8:39 PM
class CacheDelegate<T : Any>(private var initialValue: T? = null, private val factory: () -> T) {

    operator fun getValue(owner: Any, property: KProperty<*>) : T {
        if (initialValue == null) {
            initialValue = factory()
        }
        return initialValue!!
    }

    operator fun setValue(owner: Any, property: KProperty<*>, value : T)  {
        initialValue = value
    }
    
    fun invalidate() {
        initialValue = null
    }
}

class TestClass(
    testValueDel : CacheDelegate<Int>
)  {
    var testValue: Int by testValueDel
}

fun main() {
    val delegate = CacheDelegate {
        4
    }
    val testClass = TestClass(delegate)

    
    val x = testClass.testValue
    
    testClass.testValue = 234

    ...
    
    delegate.invalidate()
}
b

bbaldino

03/19/2019, 8:41 PM
yeah i was thinking i'll just keep a
var dirtyFlag: Boolean
in
TestClass
and pass that as a property reference to
CacheDelegate
, so that way i can avoid a separate member for the delegate
still an extra member, but feels a little more natural
s

streetsofboston

03/19/2019, 8:42 PM
Depends.. It depends what part of your code is managing the caching of these values. In my example,
TestClass
doesn’t have to worry about invalidating caches, nor the code that uses the
TestClass
.
b

bbaldino

03/19/2019, 8:42 PM
i think i'll end up with something like that, but it'll be a bit more complex as i want the cached field to be lazy as well
true, for my case it makes more sense for the class itself to manage
s

streetsofboston

03/19/2019, 8:42 PM
The
CacheDelegate
class here is lazy… 🙂 Ah.. yep, then just a simple boolean suffices; maybe add
get()
and
set(value)
for those properties …
b

bbaldino

03/19/2019, 8:44 PM
ah, i do see now that it's lazy...i'm just a bit paranoid about it being as threadsafe as the built-in
lazy
so i guess i'll have to end up copying it and tweaking for the reset
actually, passing the prop reference makes resetting it a bit awkward...so i guess i will go with the
invalidate
method