kotlin - 在内部对象之后初始化伴随对象
问题描述
假设我想创建一个密封的类,里面装满了一些对象。然后我想创建所有这些对象的列表,所以我在伴生对象中创建列表:
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
解决方案
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!!
}
}
}
这是 always 的单例。这只是另一种方法。但是 Initializer 对象看起来更干净。
推荐阅读
- javascript - 如何使用js为各种其他div赋予各种宽度
- python - Python:将用户指定的某些列写入新文件
- tinymce - tinyMCE.execCommand 中的 user_interface 参数有什么作用?
- eclipse - Eclipse 的 Visual Studio 键盘映射错误
- wordpress - 带有 ECS、EFS 和 ELB 的 AWS 上的 WordPress 返回 502
- deployment - 该模块尚未部署。NetBeans IDE 8.2
- python - 多 GPU 在 keras 中不起作用。得到错误
- angular - 设置 ngx-graphs,TouchEvent 错误
- macos - 从 OSX 上的命令行打开文件 url
- scala - IntelliJ IDE 中 Scala 应用构造函数模式的快速文档