必须在val变量中初始化错误

时间:2020-02-20 12:24:01

标签: android kotlin

以下代码报告property must be initialized or be abstract错误。

// MyApi.kt
interface MyApi {

    ...
}

// MyFetch.kt
class MyFetch {

    private val myApi: MyApi  // <- this line

    ...
}

它可以在可变变量中使用lateinit语句,但是我应该如何在val中预定义?

3 个答案:

答案 0 :(得分:1)

由于Kotlin中没有preinit null类型,因此实际上您必须在创建对象时在变量声明中或在init{}块中初始化变量。

由于您的变量是val而不是var,因此您无法在创建后对其进行设置,因此没有必要创建变量。

如果您打算稍后再初始化变量,但仅初始化一次,请检查以下答案:https://stackoverflow.com/a/48445081/11377112 这是通过这样的委托完成的:

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

现在您可以通过委托来委托变量

var property: Int by InitOnceProperty()

答案 1 :(得分:1)

关注点分离设计模式将倾向于将值传递给构造函数。因此,其他一些实例化您的MyFetch类的类也将实例化您的MyApi实例并将其传递给构造函数:

class MyClass(val myApi: MyApi){

}

//Some higher level class:
val myAPI = object: MyApi { //... }
val myClass = MyClass(myApi)

但是您也可以只在类中对其进行初始化。如果MyApi与MyClass的行为紧密耦合,这将是有道理的:

class MyClass {

    val myApi = object: MyApi { //... }

}

// or

class MyClass {

    val myApi: MyApi

    init {
        myApi = object: MyApi { //... }
    }
}

在这三种情况中的任何一种情况下,都必须在构造函数中,声明中或在val块中分配只读init属性的值。唯一的其他选择是使用属性委托。

答案 2 :(得分:0)

您可以使用惰性,也可以使其为空

private val myApi: MyApi? = null