ProgrammatieBackend ontwikkelaar

Leg de nuances uit van het werken met de 'object' operator in Kotlin: wat zijn singleton-objecten, objectuitdrukkingen, objectverklaringen en compagnon-objecten. Geef voorbeelden van gebruik en mogelijke fouten.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Kotlin breidt het klassieke begrip singleton uit met het sleutelwoord object. Hiermee worden de volgende patronen geïmplementeerd:

  • Objectverklaring (object declaration) — creëert een enkele instantie voor de hele applicatie (object Logger { ... }).
  • Objectuitdrukking (object expression) — creëert een anoniem object direct op de gebruiksplaats, bijvoorbeeld voor het implementeren van interfaces of gebeurtenisbehandelaars.
  • Compagnon-objecten (companion object) — stellen je in staat om statische leden in een klasse te verklaren.

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:

  • Compagnon-objecten zijn zichtbaar als statische velden op bytecode-niveau.
  • Compagnon-objecten kunnen interfaces implementeren.
  • Objectuitdrukkingen zijn geen singleton en worden elke keer aangemaakt wanneer ze worden aangesproken.
  • Objectverklaringen worden lui geïnitialiseerd, bij de eerste oproep.

Vraag met een valstrik.

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

Voorbeelden van echte fouten als gevolg van onbekendheid met de nuances van het onderwerp.


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.