I want to do a lazy initialization for a var
property. Since by lazy
is restricted only to val
properties I have to write something like this:
private var currentContextProvider: ContextProvider? = null
get() {
if (field == null) {
field = DefaultContextProvider()
}
return field
}
And now I have to deal with those pointless nullability-aware calls: currentContextProvider?.getContext()
or alternatively currentContextProvider!!.getContext()
Am I doing something wrong?
Instead of making it nullable, you can decide to initialise it with some default value, which on first access will be replaced with the lazily calculated value:
private val noInit = "noinit"
var currentContextProvider: String = noInit
get() = if (field == noInit) {
synchronized(this) {
return if (field == noInit) "lazyinit" else field
}
} else field
(I've replaced the ContextProvider
with String
)
The following implements a custom delegate reusing the former solution. It can be used just like lazy()
by defining var currentContextProvider: ContextProvider by LazyMutable { DefaultContextProvider() }
class LazyMutable<T>(val initializer: () -> T) : ReadWriteProperty<Any?, T> {
private object UNINITIALIZED_VALUE
private var prop: Any? = UNINITIALIZED_VALUE
@Suppress("UNCHECKED_CAST")
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return if (prop == UNINITIALIZED_VALUE) {
synchronized(this) {
return if (prop == UNINITIALIZED_VALUE) initializer().also { prop = it } else prop as T
}
} else prop as T
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
synchronized(this) {
prop = value
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With