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

and then:

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


    controlObj = view.findViewById(...)

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

return view

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

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个关键词吗?在初始化之后,编译器知道它是不可变的?

I am aware of the potential concurrency issues here but if I dare to access it before init, I surely deserve to be thrown美元.

推荐答案

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
    }
}

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

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相关问答推荐

在Kotlin中处理结果的高阶函数

Kotlin:有限的并行性并不是限制并行性

T和T有什么区别:任何>

捕捉异常是Kotlin协程中的反模式吗?

为什么使用 return instance ?: synchronized(this) { instance ?: PreferenceParameterState(context) } 时无法获得单例?

列表在 android WebView 中没有正确迭代

循环中的每个元素都应填充行中可用的所有可用空间

我可以在 Kotlin 中使用接口类型作为构造函数参数吗

Android 导航组件 - 向上导航打开相同的片段

Kotlin RxJava 可空的错误

Kotlin - 当表达式返回函数类型

Kotlin 中多个 init 块的用例?

如何禁用智能投射突出显示 Kotlin?

`DataBindingUtil` 中的 `bind`、`inflate` 和 `setContentView` 有什么区别

变量后的Android问号

Kotlin协程无法处理异常

Kotlin 警告:Conditional branch result of type ... is implicity cast of Any?

内联 onFocusChange kotlin

判断EditText是否为空kotlin android

Kotlin Flow 收集后无法执行代码