假设我要创建一个密封的类,其中填充了一些对象。然后,我想创建所有此类对象的列表,因此我在伴侣对象中创建列表:
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假定list包含非空值。
我知道上面的例子很简单,可以用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
答案 0 :(得分: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!!
}
}
}
这是始终的单例。这是另一种方式。但是Initializer对象看起来更干净。