Kotlin rozszerza klasyczne pojęcie singletona poprzez słowo kluczowe object. Przy jego pomocy realizowane są następujące wzorce:
object Logger { ... }).Przykład obiektu singleton:
object DatabaseManager { fun connect() { /*...*/ } } DatabaseManager.connect()
Wyrażenie obiektu:
val listener = object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { /*...*/ } }
Obiekt towarzyszący:
class User { companion object Factory { fun create(name: String) = User() } } val user = User.create("Ivan")
Szczegóły:
Jaka jest różnica między companion object a object declaration? Czy wszystkie ich człony są dostępne jako statyczne?
Odpowiedź:
object declaration — globalny singleton, człon klasy, interfejsu lub poziomu zewnętrznego.companion object — specyficzny typ deklaracji obiektów wewnątrz klasy, których człony można wywoływać tak, jakby były statyczne (przez nazwę klasy). Jednak w przeciwieństwie do Javy, są to w rzeczywistości pola obiektu singleton.Przykład różnicy:
class A { companion object { fun foo() {} } object NestedObj { fun bar() {} } } A.foo() // OK A.NestedObj.bar() // OK, ale to nie jest metoda statyczna
Historia
Programista zdefiniował mutable state wewnątrz deklaracji obiektu i zaczął go używać z różnych wątków bez synchronizacji, nie uwzględniając, że obiekty singleton są współdzielone w całej aplikacji i mogą prowadzić do warunków wyścigu.
Historia
Przy deklaracji obiektu zamiast obiektu towarzyszącego wewnątrz klasy wymagano korzystania z metod statycznych, ale musieli je wywoływać przez instancję, co pogorszyło czytelność i spowodowało błędy podczas migracji z Javy.
Historia
W kodzie UI programista za każdym razem tworzył nowy obiekt przez wyrażenie obiektu dla obsługi zdarzeń. Mylnie sądził, że to singleton i stan będzie zachowywany; w rezultacie wystąpiły wycieki pamięci z powodu niewłaściwego zarządzania cyklem życia.