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