I would like to assign one property either lazy or in a "normal way", but the problem is, that my value is always cast to "Any". I cannot use the "by" keyword, when I assign a property conditionally. Here is my current approach
abstract class IWorkerContract(private val isLazy: Boolean = false) {
private val workRequest = if (isLazy) {
// Type mismatch. Required: OneTimeWorkRequest Found: Lazy<OneTimeWorkRequest>
lazy {
OneTimeWorkRequestBuilder<Worker>.build()
}
} else {
OneTimeWorkRequestBuilder<Worker>.build()
}
}
abstract class IWorkerContract(private val isLazy: Boolean = false) {
private val lazyMgr = ResettableLazyManager()
private val workRequest by if (isLazy) {
// Type 'TypeVariable(<TYPE-PARAMETER-FOR-IF-RESOLVE>)' has no method 'getValue(Test, KProperty<*>)' and thus it cannot serve as a delegate
resettableLazy(lazyMgr) {
OneTimeWorkRequestBuilder<Worker>.build()
}
} else {
OneTimeWorkRequestBuilder<Worker>.build()
}
class ResettableLazy<PROPTYPE>(
private val manager: ResettableLazyManager,
private val init: () -> PROPTYPE,
) : Resettable {
@Volatile
private var lazyHolder = initBlock()
operator fun getValue(thisRef: Any?, property: KProperty<*>): PROPTYPE = lazyHolder.value
override fun reset() {
lazyHolder = initBlock()
}
private fun initBlock(): Lazy<PROPTYPE> = lazy {
manager.register(this)
init()
}
}
fun <PROPTYPE> resettableLazy(
manager: ResettableLazyManager,
init: () -> PROPTYPE,
): ResettableLazy<PROPTYPE> = ResettableLazy(manager, init)
You could split it up in 2 separate variables:
abstract class IWorkerContract(private val isLazy: Boolean = false) {
private val lazyWorkRequest by lazy {
OneTimeWorkRequestBuilder<Worker>.build()
}
private val workRequest
get() = when {
isLazy -> lazyWorkRequest
else -> OneTimeWorkRequestBuilder<Worker>.build()
}
}
Because of get()
, lazyWorkRequest
will not be initialised immediately but only when needed.
But more importantly: why is this behaviour needed, what is the harm of always using lazy?
Also, what is the intended purpose of ResettableLazy
? It looks like all you want to have a var
and this is the solution to solve the missing getValue()
or Type mismatch
. Is that correct?
It feels to me your question is too specific, too technical. Could you explain without using Kotlin what kind of behaviour you need?