Допустим, я хочу создать закрытый класс, заполненный некоторыми объектами.Затем я хочу создать список всех таких объектов, поэтому я создаю список в объекте-компаньоне:
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]
.Это вдвойне проблематично, поскольку Котлин предполагает, что список содержит ненулевые значения.
Я знаю, что приведенный выше пример достаточно прост, чтобы я мог заменить 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
)
}
}
}
Вышеупомянутое решение выглядит хорошо и не вызывает много плиты котла, но оно создает одиндополнительный объект, который живет навсегда для каждого свойства в объекте-компаньоне.Мне также нужно было бы повторить ключевое слово lazy для любых дополнительных свойств.
Перемещение инициализации в другой объект
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