ProgrammatieBackend ontwikkelaar

Wat is een sealed interface in Kotlin, hoe werkt het en waarvoor wordt het gebruikt? Beschrijf de gebruikskenmerken, beperkingen en geef een voorbeeld.

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

Achtergrond:

Sealed interfaces zijn in Kotlin ontstaan als een uitbreiding van het concept van sealed classes. Tot Kotlin 1.5 konden alleen sealed classes het aantal mogelijke afgeleiden klassen beperken, wat bijzonder belangrijk is voor veilige werking met toestandsstructuren (state machines, DSL, etc.). Door sealed interfaces in te voeren, kregen ontwikkelaars de mogelijkheid om op vergelijkbare wijze implementaties van interfaces te beperken, zonder aan klassen gebonden te zijn.

Probleem:

Een gewone open interface kan overal in de applicatie worden geïmplementeerd, wat kan leiden tot een ongecontroleerde toename van implementaties en een complicatie van de codeondersteuning. Bij het verwerken met een when-expressie kan de compiler niet waarschuwen voor ongecontroleerde takken.

Oplossing:

Een sealed interface beperkt implementaties tot diegene die in hetzelfde module (of hetzelfde bestand, als de interface geen top-level is) zijn gedefinieerd. Dit type controle wordt toegepast voor veilige enum-achtige structuren, het ADT-patroon en statusbeheerders. De compiler kent alle implementaties en helpt bij het code-analyse.

Voorbeeldcode:

sealed interface NetworkResult class Success(val data: String): NetworkResult class Error(val cause: Throwable): NetworkResult object Loading: NetworkResult fun handleResult(result: NetworkResult): String = when (result) { is Success -> "Success with ${result.data}" is Error -> "Error: ${result.cause.message}" Loading -> "Loading..." }

Belangrijke kenmerken:

  • Sealed interfaces zorgen voor een beperking van het aantal implementaties voor een betere type-veiligheid.
  • Werken met when-expressies: de compiler controleert de exhaustiveness.
  • Implementaties kunnen zowel klassen als objecten en andere sealed-typen zijn, maar alleen binnen hetzelfde module.

Vragen met een valkick.

Kan een sealed interface buiten het huidige bestand worden geïmplementeerd?

Antwoord: In tegenstelling tot sealed classes kunnen sealed interfaces in andere bestanden worden geïmplementeerd, maar alleen binnen hetzelfde module (of compilatie-eenheid, als de interface geen top-level is).

Kunnen sealed interfaces open methoden met standaardimplementaties hebben?

Ja, net als gewone interfaces kan een sealed interface default-implementaties van functies bevatten.

sealed interface Mode { fun description(): String = "Unknown mode" }

Is het mogelijk om een sealed interface te serialiseren met behulp van standaard serialisators (bijvoorbeeld kotlinx.serialization)?

Ja, maar het is nodig om expliciet alle implementaties op te geven. In Kotlinx.serialization kwam de ondersteuning voor sealed interfaces niet onmiddellijk, het is belangrijk om de te serialiseren types expliciet op te geven.

Typische fouten en anti-patronen

  • Definiëren van implementaties buiten de module
  • Overmatig gebruik van sealed interfaces in plaats van enum, wanneer er minder opties zijn en de structuur eenvoudiger is
  • Geen exhaustiveness check uitvoeren bij het bijwerken van een sealed interface

Voorbeeld uit het leven

Negatieve case

In een project werd een sealed interface beschreven voor alle typen UI-toestanden, maar de implementaties begonnen op verschillende plaatsen in de applicatie te verschijnen. Toen werd er een nieuw type toestand toegevoegd en vergeten om het verwerkingsblok bij te werken, wat leidde tot het negeren van de nieuwe toestand in de logs.

Voordelen:

  • Snelle toevoeging van nieuwe toestanden

Nadelen:

  • Type-veiligheid valt weg, er ontstaan ongecontroleerde logica-takken

Positieve case

Een sealed interface werd gebruikt voor alle netwerkomzetten. Hierdoor gaf de IDE direct aan alle plaatsen aan waar de verwerking via when gebeurde bij het toevoegen van een nieuw type antwoord. Fout wordt direct hersteld, geen onverwachte gaten in de logica.

Voordelen:

  • Veilige refactorering
  • Het is onmogelijk om een nieuw type toestand te vergeten

Nadelen:

  • In grote structuren kan de beperking op het aantal opties leiden tot een toename van de onderhoudsdruk.