Создание экземпляров через companion в Kotlin
Companion часто содержит фабричные функции -
они создают экземпляр класса и сразу задают
поля. Конструктор при этом делают недоступным
снаружи ключевым словом private. Вызов
снаружи идёт только через фабрику, и каждая
функция может вернуть свой экземпляр:
class Config private constructor(val path: String) {
companion object {
fun fromHome(): Config =
Config("/home/app/settings.json")
fun fromTemp(): Config =
Config("/tmp/settings.json")
}
}
fun main() {
val cfg = Config.fromHome()
println(cfg.path)
}
Запись Config.fromHome() читается как
именованный способ получить объект. Внутри
companion по-прежнему доступен private
конструктор - он виден только в теле класса и
в companion того же класса.
Фабрика может проверять аргументы и возвращать разные варианты без лишних типов снаружи:
class Email private constructor(val address: String) {
companion object {
fun parse(raw: String): Email? {
if (!raw.contains("@")) return null
return Email(raw.trim())
}
}
}
fun main() {
println(Email.parse("user@host"))
println(Email.parse("broken"))
}
Для простых неизменяемых данных иногда достаточно обычного конструктора. Фабрика в companion оправдана, когда нужно скрыть способ создания или дать несколько понятных имён вместо длинного списка параметров.
Сделайте class Version с приватным
конструктором и полем text: String.
Добавьте в companion object fun v1(): Version
и fun v2(): Version со строками
"1.0" и "2.0". Выведите
текст из результата Version.v2().
Сделайте class Range с приватным
конструктором и полями from, to.
Добавьте в companion object fun of(a: Int, b: Int): Range,
который сохраняет меньшее значение в from.
Выведите Range.of(10, 3).from.