Kotlin中Val的动态延迟初始化

时间:2020-07-07 20:07:18

标签: android kotlin lazy-initialization

我了解在Kotlin中有两种方法可以进行延迟初始化。首先是lateinit,这是动态的,但仅适用于var。其次,由lazy的委托代表val,但它是 static ,这意味着它不能在运行时初始化。
我想知道是否有一种方法可以对不可变属性(val)进行惰性动态初始化????

属性委托也像lazy一样工作,即使我们定义了一个自定义委托,它也始终是静态初始化。 (据我所知)

是否有解决方法?可以实现吗?
所以我想要的是类似lateinit val的代码,如以下代码所示:

class MyClass: SomeCallback {
    
    private lateinit val myData: String
    
    override fun onStatusChanged(status: Status, data: String) {
        if(status == Status.DataConfirmed ) {
            myData = data
        }
    }

}

1 个答案:

答案 0 :(得分:2)

我能想到的最好的方法是读写属性委托,如果您在设置它之前访问它或者多次设置它,就会抛出该委托。 Kotlin不允许您lateinitval。这可能是因为为没有属性的属性调用设置器是没有意义的。我怀疑他们是否想引入蠕虫病毒,因为它可能是模棱两可的,因此可以直接在初始化程序之外的任何地方直接设置备份字段的值。

像这样的代表应该足够。如果不足以帮助您立即解决多次调用setter的错误,我想说这是一种代码味道,说明该类太复杂了,需要分解成较小的单元。

class Once<T>: ReadWriteProperty<Any, T> {
    private object UNINITIALIZED
    private var _value: Any? = UNINITIALIZED

    override fun getValue(thisRef: Any, property: KProperty<*>): T {
        if (_value !== UNINITIALIZED) {
            @Suppress("UNCHECKED_CAST")
            return _value as T
        }
        throw UninitializedPropertyAccessException("Property [$property] was accessed before it was initialized.")
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        if (_value === UNINITIALIZED) {
            _value = value
        } else {
            error("Cannot set property [$property] more than once.")
        }
    }
}