Должна быть инициализированная ошибка в переменной val - PullRequest
1 голос
/ 20 февраля 2020

Следующий код отчета property must be initialized or be abstract ошибка.

// MyApi.kt
interface MyApi {

    ...
}

// MyFetch.kt
class MyFetch {

    private val myApi: MyApi  // <- this line

    ...
}

Может использоваться оператор lateinit в изменяемой переменной, но как я должен предопределиться в val?

Ответы [ 3 ]

1 голос
/ 20 февраля 2020

Вы фактически должны инициализировать переменную во время создания объекта в самом объявлении переменной или в блоке init{}, так как в Kotlin.

нет предопределенного нулевого типа. ваша переменная val не var вы не можете установить ее после создания, поэтому нет смысла создавать переменную.

Если вы хотели инициализировать переменную позже, но только один раз, проверьте этот ответ: { ссылка } Это делается делегированием следующим образом:

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 голос
/ 20 февраля 2020

Шаблон проектирования «Разделение проблем» предпочтет передать значение конструктору. Поэтому другой класс, который создает экземпляр вашего класса 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. Единственный другой вариант - использовать делегат свойства.

0 голосов
/ 20 февраля 2020

Вы можете использовать ленивый или сделать его обнуляемым

private val myApi: MyApi? = null
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...