以下代码报告property must be initialized or be abstract
错误。
// MyApi.kt
interface MyApi {
...
}
// MyFetch.kt
class MyFetch {
private val myApi: MyApi // <- this line
...
}
它可以在可变变量中使用lateinit
语句,但是我应该如何在val中预定义?
答案 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