如何以有条件的方式延迟或正常地分配 属性

How to assign a property either lazily or normally in a conditional way

我想懒惰地或以“正常方式”分配一个 属性,但问题是,我的值总是被强制转换为“Any”。当我有条件地分配 属性 时,我不能使用“by”关键字。这是我目前的做法

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)

value is always cast to "Any"

是的,因为函数 lazy { } 创建了 Lazy<OneTimeWorkRequest> 的新实例,而不是 OneTimeWorkRequest,这些类型是不兼容的。我不完全理解您的要求,但可以通过提供自定义 Lazy 实现来解决问题,例如

class InitializedLazy<T>(override val value: T) : Lazy<T> {
    override fun isInitialized(): Boolean = true
}

用法:

abstract class IWorkerContract(private val isLazy: Boolean = false) {
    private val workRequest by if (isLazy) {
        lazy { OneTimeWorkRequestBuilder<Worker>().build() }
    } else {
        InitializedLazy(OneTimeWorkRequestBuilder<Worker>().build())
    }
}

如果您在构造函数中访问您的 属性,if 将在实例化时计算。

class Foo(val isLazy: Boolean){
    val bar: Int by lazy { computeValue() }
    init { if (!isLazy) bar }
}

您可以将它分成 2 个单独的变量:

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()
        }
}

由于get()lazyWorkRequest不会立即初始化,只有在需要时才会初始化。

但更重要的是:为什么需要这种行为,总是使用惰性有什么危害?

此外,ResettableLazy 的预期目的是什么?看起来你想要的都是 var,这是解决缺少 getValue()Type mismatch 的解决方案。对吗?

我觉得你的问题太具体了,太技术化了。您能否在不使用 Kotlin 的情况下解释您需要什么样的行为?