Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to write a package-level static initializer in Kotlin?

Tags:

kotlin

A previous question shows how to put a static initializer inside a class using its companion object. I'm trying to find a way to add a static initializer at the package level, but it seems packages have no companion object.

// compiler error: Modifier 'companion' is not applicable inside 'file'
companion object { init { println("Loaded!") } }
fun main(args: Array<String>) { println("run!") }

I've tried other variations that might've made sense (init on its own, static), and I know as a workaround I can use a throwaway val as in

val static_init = {
    println("ugly workaround")
}()

but is there a clean, official way to achieve the same result?


Edit: As @mfulton26's answer mentions, there is no such thing as a package-level function really in the JVM. Behind the scenes, the kotlin compiler is wrapping any free functions, including main in a class. I'm trying to add a static initializer to that class -- the class being generated by kotlin for the free functions declared in the file.

like image 912
Dan Avatar asked Aug 16 '16 17:08

Dan


2 Answers

Currently there is no way to add code to the static constructor generated for Kotlin file classes, only top-level property initializers are getting there. This sounds like a feature request, so now there is an issue to track this: KT-13486 Package-level 'init' blocks

Another workaround is to place initialization in top-level private/internal object and reference that object in those functions that depend on the effect of that initialization. Objects are initialized lazily, when they are referenced first time.

fun dependsOnState(arg: Int) = State.run {
    arg + value
}

private object State {
    val value: Int
    init {
        value = 42
        println("State was initialized")
    }
}
like image 140
Ilya Avatar answered Nov 02 '22 12:11

Ilya


As you mentioned, you need a property with something that would run on initialisation:

val x = run {
    println("The package class has loaded")
}
like image 26
voddan Avatar answered Nov 02 '22 11:11

voddan