Reputation: 4712
I would like to call some code inside my class init block, after a property y is initialized. I've tried it with this::y.isInitialized
..., but the problem here is that at the creation of the class, the property is not initialized (which it gets during runtime).
class Example {
lateinit var y: String // this gets initialized after the creation of the fragment at a later time
init {
if(this::y.isInitialized) {
doStuff()
}
}
}
val testObject = Example()
testObject.y = "START INIT CODE" // here it should execute the init block
Is this even possible? Or should I change the init block with a function call after I ensure that y
is initialized?
Upvotes: 0
Views: 2013
Reputation: 1615
You can use an observable property delegate for this purpose. Here's an example:
import kotlin.properties.Delegates
class Example {
var y: Int? by Delegates.observable(initialValue = null) { _, oldValue, _ ->
if (oldValue == null) {
doStuff()
}
}
private fun doStuff() {}
}
If you need more sophisticated logic, like to allow assigning property only once, you may want to implement your own property delegate similar to the proposed.
Upvotes: 0
Reputation: 2966
you can do something like this:
class Example {
var y: String = "UNINITIALIZED"
set(value) {
if (field == "UNINITIALIZED") doStuff(value)
field = value
}
fun doStuff(y: String) {...}
}
or if you need to modify the initial value:
class Example {
var y: String = "UNINITIALIZED"
set(value) {
field = if (field == "UNINITIALIZED") doStuff(value) else value
}
fun doStuff(y: String): String {...}
}
Upvotes: 0
Reputation: 93601
The init
block is exclusively for code called at instantiation time, so it is not applicable to something that is lateinit
.
I also have to mention, a public lateinit var
in my opinion is a huge code smell. There's no way to force outside classes to treat it appropriately at compile time. lateinit
is intended for properties that are only usable (visible) after some post-construction event.
Assuming we don't care about the design issue, one way you could solve it is with a second nullable backing property.
class Example {
private var _y: String? = null
set(value) {
val needInitialization = field == null
field = value
if (needInitialization) {
// do initialization work here
}
}
var y: String
get() = _y ?: throw UninitializedPropertyAccessException("y must be initialized before getting.")
set(value) {
_y = value
}
}
Upvotes: 1