0

在初始化属性 y 之后,我想在我的类 init 块中调用一些代码。我已经尝试过this::y.isInitialized......,但这里的问题是在创建类时,属性没有初始化(它在运行时得到)。

示例类

class Example {
     lateinit var y: String // this gets initialized after the creation of the fragment at a later time

     init {
         if(this::y.isInitialized) {
            doStuff()
         }
     }

}

塞纳里奥

val testObject = Example()
testObject.y = "START INIT CODE" // here it should execute the init block

这甚至可能吗?或者我应该在确保y初始化之后使用函数调用来更改 init 块?

4

3 回答 3

1

init块专门用于在实例化时调用的代码,因此它不适用于lateinit.

我还必须提到,lateinit var在我看来,公众是一种巨大的代码气味。没有办法强制外部类在编译时适当地对待它。lateinit适用于仅在某些构建后事件之后才可用(可见)的属性。

假设我们不关心设计问题,解决它的一种方法是使用第二个可为空的支持属性。

class Example {
    private var _y: String? = null
        set(value) {
            val needInitialization = field == null
            field = value
            if (needInitialization) {
                // do initialization work here
            }
        }
    
    var y: String
        get() = _y ?: throw UninitializedPropertyAccessException("y must be initialized before getting.")
        set(value) {
            _y = value
        }
}
于 2021-01-11T18:45:54.727 回答
0

为此,您可以使用可观察的属性委托。这是一个例子:

import kotlin.properties.Delegates

class Example {
    var y: Int? by Delegates.observable(initialValue = null) { _, oldValue, _ ->
        if (oldValue == null) {
            doStuff()
        }
    }

    private fun doStuff() {}
}

如果您需要更复杂的逻辑,例如只允许分配一次属性,您可能希望实现类似于建议的自己的属性委托。

于 2021-01-11T20:04:48.117 回答
0

你可以这样做:

class Example {

    var y: String = "UNINITIALIZED"
        set(value) {
            if (field == "UNINITIALIZED") doStuff(value)
            field = value
        }

    fun doStuff(y: String) {...}
}

或者如果您需要修改初始值:

class Example {

    var y: String = "UNINITIALIZED"
        set(value) {
            field = if (field == "UNINITIALIZED") doStuff(value) else value
        }

    fun doStuff(y: String): String {...}

}
于 2021-01-11T18:42:20.540 回答