Digamos que quiero crear una clase sellada, llena de algunos objetos. Luego, quiero crear una lista de todos esos objetos, así que creo una lista en el objeto complementario:
fun main() { println(Color.Blue) println(Color.allColors) } sealed class Color { object Red : Color(); object Blue : Color(); companion object { val allColors = listOf( Red, Blue ) } } Sin embargo, el problema con el código anterior es que al llamar a Color.Blue directamente por primera vez, el objeto complementario se inicializa antes que Blue y, por lo tanto, la lista resultante contiene [Red, null] . Esto es doblemente problemático porque Kotlin asume que la lista contiene valores no nulos.
Sé que el ejemplo anterior es lo suficientemente simple como para reemplazar sealed class con enum , pero este es solo un ejemplo simplificado. En muchos casos, es beneficioso usar clases selladas sobre enumeraciones (por ejemplo, cuando necesita agregar parámetros de tipo a objetos individuales).
¿Cuál sería la mejor manera de resolver ese problema con la menor cantidad de repetitivo y asignando objetos? Se me ocurrieron dos soluciones, pero no me gusta ninguna de ellas:
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 ) } } }La solución anterior se ve bien y no causa mucho problema, pero crea un objeto adicional que vive para siempre para cada propiedad en el objeto complementario. También necesitaría repetir la palabra clave perezosa en cualquier propiedad adicional.
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 } }Este método tiene la ventaja de crear solo un objeto para todas las propiedades en el objeto complementario, pero crea una gran cantidad de repeticiones adicionales.
¿Hay una mejor manera de lograr esto?
EDITAR: Hay un problema en el rastreador de problemas de Kotlin para este caso: https://youtrack.jetbrains.com/issue/KT-8970
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!! } } }Este es el singleton de siempre. Es solo otra forma de hacerlo. Pero el objeto Initializer se ve más limpio.