Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

162
Visualizações
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 Respostas
Responde à pergunta

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda