An unexpected NPE shows up in my application when initialising an inheritor of a superclass utilising abstract val functions in its init block, this has me confused. Perhaps someone can explain why this is. FYI I solved the problem momentarily by using abstract functions instead, but I still do not understand why this happens.
My super class simply wraps another component to express the state better. In the init function there is a common enable function which can cause an immediate callback which would access the abstract vals set in the inheriting class. This causes an NPE and I do not know why, since the vals are overridden correctly in the inheriting class. Here is the code with some explaining comments of the issue:
abstract class SomeSuperClass(private val foundation: SomeFoundation) {
private val callback = object : SomeCallback() {
override fun onAvailable(network: Network) {
super.onAvailable(network)
onAvailable() // Accesses the inheritor which can cause an NPE on init
}
override fun onLost(network: Network) {
super.onLost(network)
onLost()
}
}
init {
val manager: SomeManager = SomeManager()
manager.registerCallback(callback) // Can cause an immediate callback, this is probably why the NPE happens rarely, since it does not always cause an immediate callback.
}
abstract val onAvailable: () -> Unit
abstract val onLost: () -> Unit
}
/** Singleton inheritor. */
class SomeInheritingObject private constructor(): SomeSuperClass(foundation = SomeFoundation()) {
private val _state: MutableStateFlow<State> = MutableStateFlow(State.Initial)
val state: StateFlow<State> = _state
// This overriden val is not allocated when super.init is called, why?
override val onAvailable: () -> Unit = {
_state.value = State.Available
}
override val onLost: () -> Unit = {
_state.value = State.Unavailable
}
// This is a singleton component
companion object {
private val observer: SomeInheritingObject by lazy { SomeInheritingObject() }
fun getInstance(): SomeInheritingObject = observer
}
}
I expect the overridden abstract function values to be set in super.init, perhaps they are not. In that case I'd appreciate if someone would refer me to some documentation.