В чем разница inner и nested классов в Kotlin
Что проверяют
Знаете ли вы, что в Kotlin умолчание противоположно Java, и понимаете ли, почему это сделано. За вопросом обычно стоит тема утечек памяти.
Как отвечать
Класс, объявленный внутри другого класса, в Kotlin по умолчанию вложенный: он не хранит ссылку на внешний экземпляр и не видит его членов. Чтобы получить доступ к внешнему объекту, нужно явно написать inner.
class Outer {
private val name = "outer"
class Nested { /* доступа к name нет */ }
inner class Inner { fun show() = name } // ссылка на Outer внутри
}
Outer.Nested()
Outer().Inner()Разница с Java как раз в умолчании: там внутренний класс по умолчанию хранит ссылку на внешний, и чтобы этого избежать, пишут static. Kotlin поменял поведение специально, потому что неявная ссылка это классический источник утечек: объект живёт дольше, чем должен, потому что его держит вложенный класс.
Отсюда практика в Android: адаптеры, слушатели, обработчики и любые объекты, переживающие экран, объявляются вложенными, а не inner. inner берут осознанно, когда объект действительно является частью внешнего и обязан видеть его состояние.
Полезно добавить соседние конструкции: object внутри класса это одиночка, companion object заменяет статические члены, а анонимные объекты и лямбды захватывают внешний контекст так же, как inner, и это тоже стоит помнить при работе с жизненным циклом.
Где спотыкаются
Ждут поведения Java и удивляются, что вложенный класс не видит поля внешнего.
Ставят inner по привычке и получают утечку активности через долгоживущий объект.
Путают inner с internal: первое про вложенность, второе про видимость внутри модуля.