Kotlin breidt het klassieke begrip singleton uit met het sleutelwoord object. Hiermee worden de volgende patronen geïmplementeerd:
object Logger { ... }).Voorbeeld van een singleton-object:
object DatabaseManager { fun connect() { /*...*/ } } DatabaseManager.connect()
Objectuitdrukking:
val listener = object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { /*...*/ } }
Compagnon-object:
class User { companion object Factory { fun create(name: String) = User() } } val user = User.create("Ivan")
Nuances:
Wat is het verschil tussen een compagnon-object en een objectverklaring? Zijn al hun leden toegankelijk als statische leden?
Antwoord:
object declaration — globale singleton, lid van een klasse, interface of extern niveau.companion object — een speciale vorm van objectverklaring binnen een klasse, waarvan de leden kunnen worden aangeroepen alsof ze statisch zijn (via de naam van de klasse). Echter, in tegenstelling tot Java, zijn dit eigenlijk velden van een singleton-object.Voorbeeld van het verschil:
class A { companion object { fun foo() {} } object NestedObj { fun bar() {} } } A.foo() // OK A.NestedObj.bar() // OK, maar dit is geen statische methode
Verhaal
Een ontwikkelaar definieerde mutable state binnen een objectverklaring en begon het te gebruiken vanuit verschillende threads zonder synchronisatie, zich niet realiserend dat singleton-objecten worden gedeeld door de gehele applicatie en daardoor race condition kunnen veroorzaken.
Verhaal
Bij het verklaren van een object in plaats van een compagnon-object binnen een klasse was het nodig om statische methoden te gebruiken, maar deze moesten via de instantie worden aangeroepen, wat de leesbaarheid verslechterde en fouten veroorzaakte bij migratie van Java.
Verhaal
In UI-code maakte de programmeur telkens een nieuw object via objectuitdrukking voor de gebeurtenisbehandelaar. Hij dacht ten onrechte dat het singleton was en de status zou worden behouden; als gevolg daarvan ontstonden er geheugenlekken door verkeerde omgang met de levenscyclus.