Как проверить, инициализируется ли lateinit var извне класса? - Kotlin - PullRequest
0 голосов
/ 20 марта 2020

В этом посте SO описано, как проверить, инициализирована ли переменная lateinit. Однако в этом примере переменная lateinit удобно расположена в одном и том же классе.

Как сделать то же самое с вне класса? Вот такая у меня ситуация:

Foo.kt

class Foo {
    lateinit var foo: String
}

Bar.kt

class Bar {
    fun doSomething() {
        val foo = Foo().foo
        if (::foo.isInitialized) { // Unsupported [reference to variables aren't supported yet]
            Log.i("TAG", "do something")
        }
    }
}

Что обходной путь для этого?

Ответы [ 2 ]

2 голосов
/ 20 марта 2020

Если бы это сработало, вам нужно было бы сделать

val foo = Foo()
if (foo::foo.isInitialized)
    //... 

То, как вы это делаете, вы пытаетесь получить ссылку на свойство вашей локальной переменной, которая не ' собственность Вот почему ошибка говорит «ссылка на переменные пока не поддерживается», а не «поле поддержки не доступно в данный момент». Кроме того, вы будете получать доступ к получателю свойства lateinit при назначении локальной переменной, поэтому он потерпит неудачу, если он еще не был инициализирован.

Но это не работает из-за ограничений компилятора. Вы могли бы просто добавить геттер

val fooReady: Boolean get() = ::foo.isInitialized 

Но я бы сказал, что дизайн имеет очень плохую инкапсуляцию, если внешним классам нужно проверить, инициализируется ли конкретное свойство publi c. На мой взгляд, любое использование isInitialized - это запах кода с самого начала. Если вам нужно охранять вызовы к получателю с помощью isInitialized, вы можете вместо этого сделать свойство обнуляемым. Тогда вы можете использовать знакомые идиомы нулевых проверок вместо того, чтобы прибегать к рефлексии, и это будет работать привычным образом даже для внешних классов, которые обращаются к нему.

1 голос
/ 20 марта 2020

Если объект другого класса должен принять решение, основываясь на том, инициализировано ли свойство, то инициализация этого свойства - или ответ на вопрос, было ли оно уже инициализировано - является публичной c способностью вашего бизнеса. объекта, и поэтому я бы порекомендовал вам просто сделать его частью вашего publi c API через функцию public fun isFooInitialised(): Boolean, которая использует тот факт, что сам объект может проверять состояние своих lateinit свойств.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...