Что такое ключевое слово object в Kotlin и как его использовать
Что проверяют
Понимаете ли вы три разных применения object и чем объект-компаньон отличается от статики Java. Следом обычно спрашивают, потокобезопасна ли инициализация синглтона и почему object с состоянием опасен в Android.
Как отвечать
Ключевое слово встречается в трёх формах:
- объявление объекта (
object Analytics { ... }): класс и его единственный экземпляр сразу. Инициализируется лениво при первом обращении через механизм загрузки класса JVM, поэтому потокобезопасен без ручных блокировок; - объект-компаньон (
companion objectвнутри класса): доступ через имя класса, как к статике, но это настоящий объект с именемCompanion. Он может реализовывать интерфейсы и быть получателем функций-расширений. Для Java-кода нужны@JvmStaticи@JvmField, аconst valработает только с примитивами иString; - объектное выражение (
object : TextWatcher { ... }): анонимный объект на месте, аналог анонимного класса Java. Может наследовать класс и несколько интерфейсов и, в отличие от Java, менять захваченные локальныеvar.
Отдельно стоит упомянуть data object: синглтон с читаемым toString(), удобен для состояний в sealed interface, например data object Loading : UiState.
Для Android добавьте практику: object живёт столько же, сколько процесс, и переживает пересоздание Activity. Поэтому в нём нельзя держать Context экрана, View или колбэки, которые их захватывают. Зависимости вроде репозиториев лучше отдавать через Hilt с @Singleton, чем через глобальный object: такой синглтон легко подменить в тестах.
Где спотыкаются
Называют компаньон статическим членом. Из Kotlin выглядит похоже, но без @JvmStatic из Java придётся писать MyClass.Companion.method(), и в байткоде это вызов метода экземпляра.
Кладут в object ссылку на Activity или Context. Экран закрылся, а синглтон держит его в памяти, LeakCanary находит такое сразу.
Не знают ограничения объектных выражений: тип анонимного объекта сохраняется только в локальной или приватной декларации. Из публичной функции вернётся объявленный супертип, и добавленные в объект поля станут недоступны.