I'm learning Kotlin while writing an Android app and I'm coming across an interesting problem with my code due to the order of execution of parent constructors and initialization.
I created a simpler example of what I'm experiencing:
class IntHolder(var i: Int)
open class A(var i: Int) {
init {
println("A init block id: ${getId()}") // this line calls getId() triggering the NPE
}
open fun getId(): String {
return "A${i.toString()}"
}
override fun toString(): String {
return "A-(i={$i})"
}
}
class B(i: Int, var h: IntHolder): A(i) {
init {
println("B init block i = ${i}")
println(" `${doSomething()}`")
}
override fun getId(): String {
return "B-${h.i}-${super.getId()}" // NPE on this line
}
override fun toString(): String {
return "B(i=${i})"
}
fun doSomething(): String {
return "something ".repeat(i)
}
}
fun main() {
println("creating object a = A(4)")
val a = A(4)
println("creating object b = B(6)")
val b = B(6, IntHolder(8)) // This is the line in main at the start of the stack trace
println(b.doSomething())
}
or there is an editable copy here: https://pl.kotl.in/17GKHAFRa
This causes a NullPointerException when B's constructor calls A's constructor which calls getId() and since this is really an object of class B that is B.getId() and B's getId() references members of B but they haven't been initialized to the value passed into the constructor yet so I get a NullPointerException.
In reality the base class, represented by B, is mine and the parent class, represented by A, is a Java class from an Android library.
How would you recommend fixing this?
Edit:
The Base class I'm inheriting from is android.opengl.GLSurfaceView and the function being called is getHolder. It's called in init, which is called by the various constructors.
I'm following this tutorial for using a GLSurfaceView in a Live Wallpaper and it talks about overriding getHolder to call [WallpaperService.Engine].getSurfaceHolder() but was unspecific as to how so I passed WallpaperSerice.Engine into my class that inherits from GLSurfaceView so its getHolder can call it's getSurfaceHolder
Ais from the Android SDK then this could be an XY problem. Are you sure you are usingAcorrectly? Can you actually name which class from which Android libraryAis? In any case,AcallinggetIdin the constructor like that suggests that the ID is supposed to be computed from at mosti.GLWallpaperServiceclass which containsGLEnginewhich then contains theWallpaperGLSurfaceView. arrange your classes in this way and thegetSurfaceHolder()issue will be resolved.