3

This SO post outlines how to test if a lateinit var has been initialized. However, in the example, the lateinit var is conveniently located within the same class.

How do you do the same thing from outside the class? This is the situation I have:

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

What's the workaround for this?

El Sushiboi
  • 428
  • 7
  • 19

3 Answers3

5

If this was going to work, you'd need to do

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

The way you're doing it, you're trying to get a property reference of your local variable, which isn't a property. That's why the error says "reference to variables aren't supported yet" rather than "backing field not accessible at this point". Also, you'd be accessing the getter of the lateinit property when assigning the local variable, so it would fail if it weren't initialized yet.

But it doesn't work because of compiler limitations. You could simply add a getter

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

But I would say the design has very poor encapsulation if outside classes need to check whether a particular public property is initialized yet. In my opinion, any use of isInitialized is a code smell to begin with. If you need to guard calls to the getter with isInitialized, you might as well make the property nullable instead. Then you can use the familiar idioms of null checks instead of resorting to reflection, and it will work in a familiar way even for external classes that access it.

Tenfour04
  • 83,111
  • 11
  • 94
  • 154
  • 2
    the idea here was that I wanted to use lateinit because the variable would never be null (except for when it hasn't yet been initialized) I am aware that I could simply make the variable nullable, but that would suggest "null" would be legitimate state of the variable, which is not. – El Sushiboi Mar 20 '20 at 21:05
0

If object of another class has to make a decision based on whether or not the property is initialised, then having this property initialised - or answering whether or not it has already been initialised - is a public business capacity of your object and therefore I would recommend you to simply make it a part of your public API via public fun isFooInitialised(): Boolean function that utilises the fact that the object itself can inspect the state of its lateinit properties.

ryfterek
  • 669
  • 6
  • 17
0
latinit var foo


if (this::foo.isInitialized)
scott007
  • 1
  • 2