Kotlin расширяет классическое понятие singleton через ключевое слово object. С его помощью реализуются следующие паттерны:
object Logger { ... }).Пример singleton-объекта:
object DatabaseManager { fun connect() { /*...*/ } } DatabaseManager.connect()
Объектное выражение:
val listener = object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { /*...*/ } }
Компаньон-объект:
class User { companion object Factory { fun create(name: String) = User() } } val user = User.create("Ivan")
Нюансы:
В чём разница между companion object и object declaration? Все ли их члены доступны как статические?
Ответ:
object declaration — глобальный singleton, член класса, интерфейса или внешнего уровня.companion object — особый вид object declaration внутри класса, чьи члены можно вызывать как будто они статические (через имя класса). Однако в отличие от Java, они на самом деле поля singleton-объекта.Пример различия:
class A { companion object { fun foo() {} } object NestedObj { fun bar() {} } } A.foo() // OK A.NestedObj.bar() // OK, но это не статический метод
История
Разработчик определил mutable state внутри object declaration и начал использовать его из разных потоков без синхронизации, не учитывая, что singleton-объекты шарятся на все приложение и могут стать причиной race condition.
История
При объявлении объекта вместо companion object внутри класса требовалось использование статических методов, но их пришлось вызывать через instance, что ухудшило читаемость и вызвало ошибки при миграции с Java.
История
В UI-коде программист каждый раз создавал новый объект через object expression для обработчика событий. Он ошибочно полагал, что там singleton и state будет сохраняться; в результате возникли утечки памяти из-за неправильного обращения с жизненным циклом.