I’m having trouble understanding companion object ...
# getting-started
h
I’m having trouble understanding companion object initialization in this example from my project. I have a field-less property that returns an array of objects, and I have print statements for debugging in the getter and the init block of the companion object, but somehow the latter runs after the former. As such, the array contains
null
and I get a NullPointerException. I know that this can be caused if the constructor indirectly references itself, but I do not see how that could possibly be the case (see below). Here is the code:
Copy code
object StateMessages {
    val parsers get() = arrayOf<MessageParser<*, *>>(Locate, Profile)
        .also { logInfo(it.contentToString()) }

    // ...

    data class Locate(val username: String, val state: LocateState) : ParsedMessage {
        companion object : MessageParser<String, Locate>, Requester<String, Locate> by LocateRequester {
            init {
                logInfo("initializing StateMessages.Locate")
            }

            private val locateRegex = Regex("TODO")

            override fun match(input: Component): Locate? {
                val values = locateRegex
                    .matchEntireUnstyled(input)
                    ?.namedGroupValues
                    ?: return null
                val player = values["player"].takeUnless(String::isEmpty) ?: mc.player?.username ?: return null
                val node = nodeByName(values["node"])
                val state = if (values["mode"].isEmpty()) {
                    LocateState.AtSpawn(node)
                } else {
                    val mode = PlotMode.ID.entries.singleOrNull { it.descriptor == values["mode"] } ?: return null
                    val plotName = values["plotName"]
                    val plotID = values["plotID"].toUIntOrNull() ?: return null
                    val owner = values["owner"]
                    val status = values["status"].takeUnless(String::isEmpty)

                    LocateState.OnPlot(node, Plot(plotName, owner, plotID), mode, status)
                }
                return Locate(player, state)
            }
        }
    }

    // ...
}
And here are the printed logs:
Copy code
[11:35:59] [Render thread/INFO]: [recode] [null, io.github.homchom.recode.multiplayer.message.StateMessages$Profile$Companion@231fb80f]
[11:35:59] [Render thread/INFO]: [recode] initializing StateMessages.Locate
Any ideas? Thanks in advance.
j
Do you have a way to reproduce this? This works fine in the playground: https://pl.kotl.in/n0QgXVGIL
h
I know that this can be caused if the constructor indirectly references itself, but I do not see how that could possibly be the case (see below).
Found the issue; it was this, but with a closure (so I was looking in the wrong place). Thanks anyway :)