Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

163
Vistas
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 Respuestas
Responde la pregunta

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 Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda