В Kotlin любой класс может иметь один первичный конструктор (указывается в объявлении класса) и несколько вторичных конструкторов (через constructor).
private, protected, internal, public) можно скрывать или ограничивать видимость конструкторов.Пример с первичным и вторичным конструкторами:
open class Person(val name: String) { constructor(name: String, age: Int) : this(name) { // вторичный конструктор } } class Employee : Person { constructor(name: String) : super(name) // Обязателен явный super }
Модификаторы видимости:
class Secret private constructor() { companion object { fun create() = Secret() } } val s = Secret.create() // Ok, а Secret() - ошибка
Нюансы:
Можно ли в Kotlin унаследовать класс и не вызывать его первичный конструктор?
Ответ: Нет. В Kotlin при наследовании всегда должен быть вызван хотя бы один конструктор родителя — либо первичный, либо вторичный (через super()).
Пример:
open class A(val x: Int) class B: A // Ошибка: требуется явно вызвать конструктор A
История
В команде пытались запретить создание объектов класса напрямую и сделали конструктор private. Однако забыли реализовать фабричный метод. Это привело к невозможности протестировать класс без рефлексии и блокировке CI.
История
Наследовали класс с обязательными параметрами в первичном конструкторе, но не передали их при объявлении наследника. Это выявили только на этапе компиляции после долгой отладки.
История
При использовании вторичных конструкторов забыли, что все они обязаны вызывать первичный. В результате объекты инициализировались без нужных параметров, что привело к NullPointerException в рантайме.