Kotlin 在内部对象之后初始化伴随对象

Kotlin 在内部对象之后初始化伴随对象,kotlin,initialization-order,sealed-class,Kotlin,Initialization Order,Sealed Class,假设我想创建一个密封的类,填充一些对象。然后我想创建所有这些对象的列表,所以我在companion object中创建列表: fun main() { println(Color.Blue) println(Color.allColors) } sealed class Color { object Red : Color(); object Blue : Color(); companion object { val allColor

假设我想创建一个密封的类,填充一些对象。然后我想创建所有这些对象的列表,所以我在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
        )
    }
}
然而,上面代码的问题是,当第一次直接调用
Color.Blue
时,伴随对象在
Blue
之前初始化,因此结果列表包含
[红色,null]
。这是双重问题,因为Kotlin假设列表包含非空值

我知道上面的示例非常简单,我可以用
enum
替换
sealed class
,但这只是一个简化的示例。在许多情况下,在枚举上使用密封类是有益的(例如,当您需要向单个对象添加类型参数时)

用最少的样板和分配对象来解决这个问题的最佳方法是什么?我想出了两个解决办法,但我不喜欢其中任何一个:

懒惰的 上面的解决方案看起来很好,不会造成太多的锅炉板,但它会创建一个额外的对象,该对象对伴生对象中的每个属性都永久存在。我还需要在任何其他属性上重复lazy关键字

将初始化移动到另一个对象中
fun main(){
println(颜色:蓝色)
println(Color.allColors)
}
密封类颜色{
对象红色:颜色();
对象蓝色:颜色();
私有对象初始值设定项{
val allColors=listOf(
红色
蓝色
)
}
伴星{
val所有颜色:列表
get()=初始值设定项.allColors
}
}
这种方法的一个优点是只为伴生对象中的所有属性创建一个对象,但它会创建许多额外的样板文件

有没有更好的方法来实现这一点

编辑:对于这种情况,Kotlin issue tracker上有一个问题:

密封类颜色(var-meh:Int){
对象红色:颜色(10)
对象蓝色:颜色(20)
伴星{
私有变量colorsList:列表?=null
val所有颜色:列表
get()=颜色列表?:运行{
colorsList=listOf(
红色
蓝色
)
颜色列表!!
}
}
}

这是永远的单身汉。这只是另一种方式。但是初始值设定项对象看起来更干净。

您可以将其设置为
fun allColors()
是的,但这将在每次调用时创建列表。是的,只是您说过,通过lazy创建
也不是最好的方法,因为
额外的对象
?所以你不介意保留这个
val
,但不想有一个
惰性的
初始值设定项?我同意,所有的解决方案都不是理想的。我只是想确保没有任何聪明的黑客来实现这一点。你也可以在你的颜色类文件的顶部调用Color.allColors。是否存在一些与此行为相关的开放问题?懒惰解决方案基本上不是这样,但样板文件较少?事实上,有很多方法可以解决此问题,但问题上已经列出了3种简单的方法。我只是添加了另一种多余的方法。我真的认为kotlin最后在主类之外初始化引用对象的行为有点危险。是否存在与此行为相关的未决问题?
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
            )
        }
    }
}
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
    }
}
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!!
            }
    }
}