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?