简体   繁体   中英

Dynamic lazy initialization for val in kotlin

I understand there are two ways for lazy initialization in kotlin. first by lateinit which is dynamic but it is only for var . second, by lazy delegate which is for val but it is static , which means it can't be initialized at runtime.
I was wondering is there a way to have lazy dynamic initialization for immutable properties( val )????

property delegation also works like lazy and even if we define a custom delegate, its always static initialization. (to my knowledge)

is there a workaround for this? could it be implemented somehow?
so what I wish for, is something like lateinit val , shown in below code:

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

}

The best I can come up with is a read-write property delegate that throws if you access it before setting it, or if you set it multiple times. Kotlin doesn't let you lateinit a val . This is likely because it would be nonsensical to call a setter for a property that doesn't have one. I doubt they want to introduce the can of worms it would be to directly set the value of a backing field from anywhere besides the initializer, because it would be ambiguous.

A delegate like this should be adequate. If it's not adequate to help you immediately fix the bug of calling the setter multiple times, I would say that's a code smell that the class is too complicated and needs to be broken up into smaller units.

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.")
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM