Kotlin如何有条件为属性选择lazy懒加载或普通赋值方式
问题原因
- 第一种直接赋值的写法中,if的两个分支分别返回
Lazy<OneTimeWorkRequest>和OneTimeWorkRequest两种无兼容关系的类型,编译器只能将属性向上推导为Any类型,因此触发类型不匹配报错。 - 第二种使用by委托的写法中,属性委托要求右侧所有分支的返回值都实现了约定的
getValue运算符方法,你else分支返回的普通OneTimeWorkRequest实例没有该方法,因此无法作为委托使用。
解决方案
推荐用统一委托类型的方式实现需求,将非懒加载的返回值也封装为符合要求的委托对象,保证if两个分支返回值类型一致。
方案1:适配自定义ResettableLazy的实现
你可以新增一个即时初始化的工厂方法,让非懒加载分支也返回ResettableLazy类型实例,同时保留reset能力:
// 扩展ResettableLazy的工厂方法,新增即时初始化重载 fun <PROPTYPE> resettableEager( manager: ResettableLazyManager, value: PROPTYPE ): ResettableLazy<PROPTYPE> { return ResettableLazy(manager, { value }).apply { // 提前触发初始化,实现非懒加载效果 getValue(null, null) } }
修改后的业务代码:
abstract class IWorkerContract(private val isLazy: Boolean = false) { private val lazyMgr = ResettableLazyManager() private val workRequest by if (isLazy) { resettableLazy(lazyMgr) { OneTimeWorkRequestBuilder<Worker>.build() } } else { resettableEager(lazyMgr, OneTimeWorkRequestBuilder<Worker>.build()) } }
该方案的优势是两个分支的返回值类型完全一致,且都支持原有reset功能,使用属性时和普通属性无差异,不需要额外调用方法。
方案2:统一使用Lazy类型(无需委托)
如果不需要reset能力,也可以直接将属性类型声明为Lazy<OneTimeWorkRequest>,非懒加载分支返回预初始化的Lazy实例即可:
// 实现预初始化的Lazy实例 fun <T> eagerOf(value: T): Lazy<T> = object : Lazy<T> { override val value: T = value override fun isInitialized(): Boolean = true } abstract class IWorkerContract(private val isLazy: Boolean = false) { private val workRequest = if (isLazy) { lazy { OneTimeWorkRequestBuilder<Worker>.build() } } else { eagerOf(OneTimeWorkRequestBuilder<Worker>.build()) } // 使用属性时调用value即可:workRequest.value }
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

