In Kotlin if you have an open class which refers to this in its constructor or init block, you (quite rightly) get a compiler warning:
Leaking 'this' in constructor of non-final class
The reason for this is explained here.
My question is: why is this not reported when the class is final? If this is used in the init block before that block has completed, the object is still not in a fully constructed state, so shouldn't the warning apply there too?
This can even lead to a situation where a val property seems to change at runtime. Take this code as an example:
class Listener {
fun onCreated(leaker: Leaker) = println("Listener hears that leaker created with a value of ${leaker.myVal}")
}
class Leaker(listener: Listener) {
val myVal: Int
init {
listener.onCreated(this)
myVal = 1
println("Leaker knows that it's been created with a value of $myVal")
}
}
Using these objects as follows:
Leaker(Listener())
will result in the following output:
Listener hears that leaker created with a value of 0
Leaker knows that it's been created with a value of 1
Notice that myVal is initially reported as being 0, then as being 1.
As can be seen, Leaker passes an instance of itself to Listener before Leaker has been fully constructed. Listener can then access the myVal property before it's been initialized, so it'll have the default value (0 in this case as it's an integer). Later on Listener then changes the value of this property (to 1 in this example). This means that the program behaves as if a val has changed.
Should the compiler warn you about this?