Ответ
init блок вызывается сразу после первичного конструктора (primary constructor) во время инициализации экземпляра класса. Порядок выполнения:
- Параметры первичного конструктора
- Свойства, объявленные в теле класса
- Блоки
init(в порядке их объявления) - Вторичные конструкторы (если есть)
class Person(name: String) {
val firstProperty = "First: $name".also(::println)
init {
println("First init: $name")
}
val secondProperty = "Second: $name".also(println)
init {
println("Second init: $name")
}
}
// Вызов: Person("Alex") выведет:
// First: Alex
// First init: Alex
// Second: Alex
// Second init: Alex Ответ 18+ 🔞
Давай разберём эту штуку, которая у новичков мозги выносит. init блок — это, ёпта, как будто ты заходишь в новую квартиру и начинаешь её обживать. Сначала ты заносишь мебель (свойства), потом вешаешь картины (первый init), потом ставишь холодильник (ещё свойства), а потом уже вешаешь полку в прихожей (второй init). И всё это — до того, как ты сядешь на диван и скажешь «ну вот, теперь живу».
Порядок — хуй с горы, его надо запомнить, иначе сам от себя охуеешь, когда код ведёт себя не так, как ожидал.
- Параметры главного конструктора. Это как адрес квартиры — он известен сразу.
- Свойства в теле класса. Всё, что объявлено через
valилиvarпрямо в теле. Они инициализируются по порядку, сверху вниз. - Блоки
init. Они тоже выполняются по порядку, сверху вниз, сразу после того, как свойства выше них проинициализировались. - Вторичные конструкторы (
constructor). Это если ты решил зайти в квартиру через чёрный ход. Они выполняются в самом конце, после всей этой кухни сinit-ами.
Вот смотри на примере, тут всё видно как на ладони:
class Person(name: String) {
val firstProperty = "First: $name".also(::println)
init {
println("First init: $name")
}
val secondProperty = "Second: $name".also(println)
init {
println("Second init: $name")
}
}
// Вызов: Person("Alex") выведет:
// First: Alex
// First init: Alex
// Second: Alex
// Second init: Alex
Видишь? Сначала отработало свойство firstProperty, потом первый init блок, который уже может этим свойством пользоваться. Потом пошло свойство secondProperty и второй init. Всё чётко по списку. Если переставить их местами — пиздец, всё полетит в другом порядке, и доверия к такому коду будет ебать ноль.
Запомни эту простую мысль: Kotlin инициализирует класс сверху вниз, как читает книжку. Сначала объявления свойств, потом init блоки, которые между ними. И так до самого конца тела класса. После этого уже можно вызывать вторичные конструкторы. Главное — не пытайся в первом же init-блоке обратиться к свойству, которое объявлено ниже по коду. Оно ещё не существует, и компилятор тебе так и скажет, только матом: «Unresolved reference», что в переводе на человеческий означает «чё за хуйню ты пытаешься сделать, чувак?».