Sealed Class — een speciaal type klasse in Kotlin dat de overervingshiërarchie beperkt tot een vaste set subtypen. Alle overervers worden in hetzelfde bestand gedeclareerd en zijn bekend bij de compiler, waardoor een uitputtend when-blok zonder verplichte else-tak mogelijk is. Volgens Kotlin Docs, 2026 zijn verzegelde klassen het belangrijkste mechanisme voor het weergeven van beperkte hiërarchieën zoals toestanden, fouttypen en UI-gebeurtenissen.
Belangrijkste punten
Sealed Class (verzegelde klasse) — dit is een klasse in Kotlin gemarkeerd met de modifier sealed. Het definieert een beperkte typehiërarchie: alle mogelijke overervers worden in hetzelfde bestand opgesomd en de compiler weet van elk van hen. Dit onderscheidt sealed class van een gewone open klasse, waarvan de overervers overal kunnen worden gedeclareerd.
Het hoofddoel van sealed class is type-veilige weergave van een eindige set varianten. Elke overerver kan een eigen gegevensstructuur hebben, wat sealed class flexibeler maakt dan enum. Tijdens runtime is sealed class een gewone abstracte klasse, de compiler legt alleen tijdens compilatie beperkingen op.
Sealed class is vooral nuttig in Android-architectuur van applicaties: UI-toestanden, resultaten van netwerkverzoeken, Intent-achtige navigatiegebeurtenissen en natuurlijk fouthiërarchieën — typische toepassingsscenario's.
Bij compilatie wordt sealed class geoptimaliseerd naar een overgangstabel voor when-expressies, wat het efficiënter maakt dan if-else-ketens. In combinatie met data class kan elke overerver niet alleen toestand, maar ook methoden bevatten, waardoor zelfdocumenterende domeinmodellen zonder boilerplate-code kunnen worden gebouwd.
Sealed class is ook effectief voor het weergeven van eindige automaten (state machine) in mobiele applicaties. Elke toestand — een afzonderlijke overerver met unieke parameters, en overgangen tussen toestanden worden gecontroleerd via de when-expressie. De compiler garandeert dat alle mogelijke toestanden zijn verwerkt, wat runtime-fouten elimineert bij het wijzigen van de UI-toestand of bedrijfslogica.
Beginnende Kotlin-ontwikkelaars verwarren sealed class vaak met enum, omdat beide de set waarden beperken. Er is echter een fundamenteel verschil: enum — een set constanten van hetzelfde type, sealed class — een hiërarchie van verschillende typen.
Enum is optimaal wanneer alle varianten constanten zijn zonder extra structuur. Bijvoorbeeld dagen van de week, bestelstatussen of actietypen zonder parameters. Elke enum-waarde is een singleton met een vaste naam.
Sealed class is nodig wanneer elke variant eigen gegevens heeft. Bijvoorbeeld een netwerkfout bevat een antwoordcode, een parsingfout — details, en een autorisatiefout — een bericht. Elke overerver van sealed class is een afzonderlijk type met unieke velden.
// Enum — alle varianten van één type
enum class Status { LOADING, SUCCESS, ERROR }
// Sealed class — elke variant met eigen gegevens
sealed class UiState<out T> {
object Loading : UiState<Nothing>()
data class Success<T>(val data: T) : UiState<T>()
data class Error(val message: String) : UiState<Nothing>()
}
Sinds Kotlin 1.5 is het mogelijk om sealed interface te declareren. Dit breidt het sealed-concept uit naar interfaces: sealed interface heeft ook een vaste set implementaties, maar ondersteunt meervoudige overerving.
Sealed interface is handig wanneer overervers meerdere contracten tegelijk moeten implementeren. Bijvoorbeeld een UI-gebeurtenis kan tegelijkertijd klikbaar en traceerbaar zijn. Met sealed class zou men één basisklasse moeten kiezen, met sealed interface implementeert de overerver beide.
Sealed class is een klasse, dus elke overerver kan slechts één ouder hebben. Sealed interface lost dit probleem op, maar kan geen toestand bevatten. De keuze hangt af van de taak: gemeenschappelijke logica met velden nodig — sealed class, flexibiliteit van contracten nodig — sealed interface.
sealed interface ScreenEvent {
data class Refresh(val force: Boolean) : ScreenEvent
data class Navigate(val route: String) : ScreenEvent
data class ShowError(val toast: String) : ScreenEvent
}
sealed interface AnalyticsEvent {
val name: String
val params: Map<String, Any>
}
// Overerver implementeert beide interfaces
data class LoginClicked(
override val name: String = "login_click",
override val params: Map<String, Any> = emptyMap()
) : ScreenEvent, AnalyticsEvent
Een van de belangrijkste toepassingen van sealed class in mobiele ontwikkeling — type-veilige fouthiërarchie. In plaats van uitzonderingen van verschillende typen te gooien of een algemene Exception te gebruiken, verzamelt sealed class alle mogelijke domeinfouten in één type.
Maak een sealed class DomainError en noem alle soorten storingen als overervers. Elke overerver bevat alleen de gegevens die zinvol zijn voor dat fouttype. De compiler garandeert dat u bij het verwerken van de fout geen variant zult vergeten.
Beschouw een applicatie met autorisatie, waar verschillende storingsscenario's mogelijk zijn: onjuist wachtwoord, accountblokkering, serverprobleem. Sealed class verenigt ze in één type met uitputtende afhandeling.
sealed class AuthError {
data class InvalidCredentials(
val attempts: Int
) : AuthError()
data class AccountBlocked(
val until: Long
) : AuthError()
data class NetworkFailure(
val cause: Throwable
) : AuthError()
object ServerError : AuthError()
}
fun handleError(error: AuthError): String = when (error) {
is AuthError.InvalidCredentials ->
"Resterende pogingen: ${3 - error.attempts}"
is AuthError.AccountBlocked ->
"Toegang geblokkeerd tot ${Date(error.until)}"
is AuthError.NetworkFailure ->
"Controleer verbinding: ${error.cause.localizedMessage}"
AuthError.ServerError ->
"Server tijdelijk niet beschikbaar"
}
Sealed class is een standaardinstrument geworden in de architectuur van Android-applicaties. Laten we drie belangrijke patronen bekijken waarin sealed class onmisbaar is in mobiele ontwikkeling.
Afzonderlijk is het vermelden waard de toepassing van sealed class in Clean Architecture. Elke laag (data, domain, presentation) gebruikt sealed class voor zijn fouttypen, en mappers zetten de ene sealed class om in de andere. Bijvoorbeeld DataError uit de gegevenslaag wordt naar DomainError voor bedrijfslogica en vervolgens naar UiState voor de presentatielaag. Dit behoudt type-veiligheid op alle niveaus van de applicatie en garandeert dat geen enkele fout onverwerkt blijft.
Testen van sealed class vereist een speciale aanpak, omdat elke overerver een afzonderlijk type is met een eigen toestand. Het wordt aanbevolen om geparametriseerde tests te schrijven die alle overervers van sealed class doorlopen. Dit garandeert that when-expressies alle varianten dekken, inclusief nieuwe toegevoegd bij uitbreiding van de hiërarchie.
Voor UI-tests maakt sealed class als UiState het mogelijk om de weergave van elke toestand te controleren: Loading toont een spinner, Content — gegevens, Error — een foutmelding. Omdat sealed class eindig is, geeft testdekking van alle toestanden volledige zekerheid over de juistheid van de UI-logica.
Ondanks de eenvoud van het concept maken ontwikkelaars regelmatig fouten bij het ontwerpen van sealed class hiërarchieën. Laten we de belangrijkste problemen en manieren om ze te vermijden bekijken.
Veelgestelde vragen
Ja, sealed class kan abstracte methoden bevatten, en elke overerver moet ze implementeren. Dit is handig wanneer alle varianten een gemeenschappelijke interface moeten bieden, maar met verschillende uitvoeringslogica.
In Java 17+ zijn verzegelde klassen en interfaces met de modifier sealed verschenen. Android ondersteunt Java 17 momenteel gedeeltelijk, maar in Kotlin-projecten is sealed class beschikbaar vanaf Kotlin 1.0 zonder beperkingen.
Ja, een sealed class kan een overerver van een andere zijn. De sealed class hiërarchie blijft eindig: de compiler kent alle overervers op elk niveau. Dit maakt het mogelijk om gedetailleerde foutclassificaties te bouwen.
Sealed class creëert geen overhead tijdens runtime. De compiler optimaliseert when-expressies met sealed class naar overgangstabellen (tableswitch), wat sneller is dan if-else-ketens. De prestaties zijn identiek aan enum.
Elke overerver van sealed class wordt afzonderlijk getest. Omdat sealed class eindig is, kan een geparametriseerde test worden geschreven die alle varianten doorloopt. Dit geeft volledige dekking van de takken van when-blokken.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook