假设我想创建一个密封的类,里面装满了一些对象。然后我想创建所有这些对象的列表,所以我在伴生对象中创建列表:
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
,因此结果列表包含[Red, null]
. 这是双重问题,因为 Kotlin 假设列表包含非空值。
我知道上面的例子很简单,我可以用 替换sealed class
,enum
但这只是一个简化的例子。在许多情况下,使用密封类而不是枚举是有益的(例如,当您需要向单个对象添加类型参数时)。
用最少的样板和分配对象来解决这个问题的最佳方法是什么?我想出了两个解决方法,但我不喜欢其中任何一个:
懒惰的
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
}
}
这种方法的好处是只为伴生对象中的所有属性创建一个对象,但它创建了许多额外的样板。
有没有更好的方法来实现这一目标?
编辑:对于这种情况,Kotlin 问题跟踪器存在问题:https ://youtrack.jetbrains.com/issue/KT-8970