Kotlin:lateinit为val,或者可以设置一次的var [英] Kotlin: lateinit to val, or, alternatively, a var that can set once

查看:305
本文介绍了Kotlin:lateinit为val,或者可以设置一次的var的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是好奇:在Kotlin中,我很想获得一些可以由lazy初始化但带有参数的val.那是因为我需要在很晚的时候创建一些东西才能对其进行初始化.

Just curious: In Kotlin, I would love to get some val that can be initialized by lazy, but with a parameter. That's because I need something that's created very late in order to initialize it.

具体来说,我希望自己有:

Specifically, I wish I had:

private lateinit val controlObj:SomeView

或:

private val controlObj:SomeView by lazy { view:View->view.findViewById(...)}

然后:

override fun onCreateView(....) {
    val view = inflate(....)


    controlObj = view.findViewById(...)

或在第二种情况下controlObj.initWith(view)或类似的内容:

or in the 2nd case controlObj.initWith(view) or something like that:

return view

我不能使用by lazy,因为by lazy不会接受初始化时要使用的外部参数.在此示例中-包含view.

I cannot use by lazy because by lazy won't accept external parameters to be used when initialising. In this example - the containing view.

我当然有lateinit var,但是如果我能确保它只有在设置后才可以读取并且可以一行完成,那会很好.

Of course I have lateinit var but it would be nice if I could make sure it becomes read only after setting and I could do it in one line.

是否有一种很干净的方法来创建一个只读变量,该变量仅初始化一次,但仅在其他一些变量诞生时才初始化?有init once关键字吗?初始化之后,编译器知道它是不可变的吗?

Is there a pretty clean way to create a read only variable that initializes only once but only when some other variables are born? Any init once keyword? That after init the compiler knows it's immutable?

我知道这里可能存在并发问题,但是如果我敢在init之前访问它,那我当然应该被抛出.

推荐答案

您可以像这样实现自己的委托:

You can implement own delegate like this:

class InitOnceProperty<T> : ReadWriteProperty<Any, T> {

    private object EMPTY

    private var value: Any? = EMPTY

    override fun getValue(thisRef: Any, property: KProperty<*>): T {
        if (value == EMPTY) {
            throw IllegalStateException("Value isn't initialized")
        } else {
            return value as T
        }
    }

    override fun setValue(thisRef: Any, property: KProperty<*>, value: T) {
        if (this.value != EMPTY) {
            throw IllegalStateException("Value is initialized")
        }
        this.value = value
    }
}

之后,您可以按以下方式使用它:

After that you can use it as following:

inline fun <reified T> initOnce(): ReadWriteProperty<Any, T> = InitOnceProperty()

class Test {

     var property: String by initOnce()

     fun readValueFailure() {
         val data = property //Value isn't initialized, exception is thrown
     }

     fun writeValueTwice() {
         property = "Test1" 
         property = "Test2" //Exception is thrown, value already initalized
     }

     fun readWriteCorrect() {
         property = "Test" 
         val data1 = property
         val data2 = property //Exception isn't thrown, everything is correct
     }

}

如果您在初始化之前尝试访问值,则将获得异常以及尝试重新分配新值.

In case when you try to access value before it is initialized you will get exception as well as when you try to reassign new value.

这篇关于Kotlin:lateinit为val,或者可以设置一次的var的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆