0

Say I have the following class:

class ExampleClass: OtherClass {
  lateinit var thing: Thing
  var thingOptional: Thing? = null
  fun exampleFun() {
    val innerThing = thing ?: Thing()
    val innerThing2 = thingOptional ?: Thing()
  }
}

Produces the following warning:

Elvis operator (?:) always returns the left operand of non-nullable type Thing

and then the following runtime exception:

lateinit property thing has not been initialized

So in my understanding an optional can be either a type, or null at any point, while a lateinit variable can be null until it is given a value and then can never be null again, and must be given a value. However quite clearly the semantics of lateinit are slightly different.

So: what is the starting value of lateinit why isn't it falsy? Is it possible to use lateinit in this way, as an optional substitute? If not, how can I create this kind of value? (allow null as a starting state, but then be non nullable)

Abraham P
  • 15,029
  • 13
  • 58
  • 126

2 Answers2

3

You still have to manually assign a value to lateinit fields before performing any reads, all that flag does is alleviates the need of initializing it in constructor. lateinit doc

As You've noticed there's no initial value of lateinit fields - it throws the exception on read, but you can manually check if it was initialized with this::thing.isInitialized.

Pawel
  • 15,548
  • 3
  • 36
  • 36
2

So basically what happens is in Kotlin, lateinit simply means that you are not required to initialize that variable when you are declaring it, but it's your responsibly to initialize it before reading or accessing it otherwise it will throw an exception at run-time.

It's basically useful when you are initializing using dependency injection.

So talking about your errors now,

Elvis operator (?:) always returns the left operand of non-nullable type Thing

You are getting above error because, you are accessing lateinit var thing before initializing it and it is stated clearly in your another error i.e.

lateinit property thing has not been initialized

Now, to answer this:

If not, how can I create this kind of value? (allow null as a starting state, but then be non nullable)

You can do this:

  class ExampleClass: OtherClass {
  var thingOptional: Thing? = null
  fun exampleFun() {
    thingOptional = Thing()// thingsOption was null initially but now it is initialized
  }
}

Hope it helps, let me know if you have any other doubt.

Keshav Aggarwal
  • 754
  • 6
  • 14