Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

161
Views
Initializing companion object after inner objects

Let's say I want to create sealed class, filled with some objects. Then I want to create list of all such objects, so I create list in companion object:

fun main() {
    println(Color.Blue)
    println(Color.allColors)
}

sealed class Color {
    object Red : Color();
    object Blue : Color();

    companion object {
        val allColors = listOf(
                Red,
                Blue
        )
    }
}

However, issue with above code is that when calling Color.Blue directly for the first time, companion object is initialized before Blue and thus resulting list contains [Red, null]. This is doubly problematic because Kotlin assumes list contains non-null values.

I know above example is simple enough that I could replace sealed class with enum, but this is just a simplified example. In many cases it is beneficial to use sealed classes over enums (for example when you need to add type parameters to individual objects).

What would be the best way to solve that issue with least amount of boilerplate and allocating objects? I've come up with two workarounds, but I do not like either of them:

Lazy

fun main() {
    println(Color.Blue)
    println(Color.allColors)
}

sealed class Color {
    object Red : Color();
    object Blue : Color();

    companion object {
        val allColors by lazy {
            listOf(
                    Red,
                    Blue
            )
        }
    }
}

Above solution looks fine and does not cause much boiler plate, but it creates one additional object that lives forever for every property in the companion object. I would also need to repeat lazy keyword on any additional properties.

Moving initialization into another object

fun main() {
    println(Color.Blue)
    println(Color.allColors)
}

sealed class Color {
    object Red : Color();
    object Blue : Color();

    private object Initializer {
        val allColors = listOf(
                Red,
                Blue
        )
    }

    companion object {
        val allColors: List<Color>
            get() = Initializer.allColors
    }
}

This method has a benefit of only creating one object for all properties in companion object, but it creates a lot of additional boilerplate.

Is there a better way to achieve this?

EDIT: There is an issue on Kotlin issue tracker for this case: https://youtrack.jetbrains.com/issue/KT-8970

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

sealed class Color(var meh:Int) {
    object Red : Color(10)
    object Blue : Color(20)

    companion object {
        private var colorsList:List<Color>? = null
        val allColors:List<Color>
            get() = colorsList?:run{
                colorsList = listOf(
                        Red,
                        Blue
                )
                colorsList!!
            }
    }
}

This is the singleton of always. It's just another way to do it. But the Initializer object looks cleaner.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!