如何以有条件的方式延迟或正常地分配 属性
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 的情况下解释您需要什么样的行为?
我想懒惰地或以“正常方式”分配一个 属性,但问题是,我的值总是被强制转换为“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 的情况下解释您需要什么样的行为?