Sealed Class — vad det är, funktionsprincip och tillämpning

Författare: IT Sectr Publicerad: 2026-05-26 Lästid: 8 min

Sealed Class — en speciell klass typ i Kotlin som begränsar arvshierarkin till en fast uppsättning subtyper. Alla arvtagare deklareras i samma fil och är kända för kompilatorn, vilket möjliggör användning av ett uttömmande when-block utan obligatorisk else-gren. Enligt Kotlin Docs, 2026 är förseglade klasser en nyckelmekanism för att representera begränsade hierarkier som tillstånd, felttyper och UI-händelser.

Huvudpunkter

  • Sealed Class — klass med en fast uppsättning arvtagare deklarerade i samma fil.
  • Exhaustive when — kompilatorn kontrollerar att alla subtyper har bearbetats, vilket eliminerar bortglömda else-grenar.
  • Sealed interface — Kotlin 1.5+ stöder förseglade gränssnitt för multipelt arv.
  • Felhierarki — sealed class är standardsättet för typsäker felhantering i Kotlin.
  • Skillnad från enum — varje arvtagare till sealed class kan innehålla unikt tillstånd och olika antal fält.

Vad är Sealed Class?

Sealed Class (förseglad klass) — är en klass i Kotlin markerad med modifieraren sealed. Den definierar en begränsad typ hierarki: alla möjliga arvtagare listas i samma fil och kompilatorn känner till var och en av dem. Detta skiljer sealed class från en vanlig öppen klass, vars arvtagare kan deklareras var som helst.

Huvudsyftet med sealed class är typsäker representation av en ändlig uppsättning varianter. Varje arvtagare kan ha sin egen datastruktur, vilket gör sealed class mer flexibel än enum. Vid körning är sealed class en vanlig abstrakt klass, kompilatorn tillämpar begränsningar endast vid kompilering.

Sealed class är särskilt användbar i Android-arkitektur för applikationer: UI-tillstånd, nätverksförfrågningsresultat, Intent-liknande navigeringshändelser och naturligtvis felhierarkier — typiska tillämpningsscenarier.

Vid kompilering optimeras sealed class till en övergångstabell för when-uttryck, vilket gör den effektivare än if-else-kedjor. I kombination med data class kan varje arvtagare inte bara innehålla tillstånd, utan även metoder, vilket möjliggör byggande av självdokumenterande domänmodeller utan boilerplate-kod.

Sealed class är också effektiv för att representera ändliga tillståndsmaskiner (state machine) i mobilapplikationer. Varje tillstånd — en separat arvtagare med unika parametrar, och övergångar mellan tillstånd styrs via when-uttrycket. Kompilatorn garanterar att alla möjliga tillstånd har bearbetats, vilket eliminerar körningsfel vid ändring av UI-tillstånd eller affärslogik.

Sealed Class och Enum: viktigaste skillnaderna

Börjande Kotlin-utvecklare förväxlar ofta sealed class med enum, eftersom båda begränsar värdeuppsättningen. Men det finns en grundläggande skillnad mellan dem: enum — en uppsättning konstanter av samma typ, sealed class — en hierarki av olika typer.

När ska man välja enum

Enum är optimal när alla varianter är konstanter utan ytterligare struktur. Till exempel veckodagar, orderstatus eller åtgärdstyper utan parametrar. Varje enum-värde är en singleton med ett fast namn.

När ska man välja sealed class

Sealed class behövs när varje variant har egna data. Till exempel innehåller ett nätverksfel svarskod, ett parsningsfel — detaljer, och ett auktoriseringsfel — ett meddelande. Varje arvtagare till sealed class är en separat typ med unika fält.

kotlin
// Enum — alla varianter av en typ
enum class Status { LOADING, SUCCESS, ERROR }

// Sealed class — varje variant med egna data
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>()
}

Sealed Interface jämfört med Sealed Class

Från Kotlin 1.5 finns möjligheten att deklarera sealed interface. Detta utökar sealed-konceptet till gränssnitt: sealed interface har också en fast uppsättning implementationer, men stöder multipelt arv.

När ska man använda sealed interface

Sealed interface är praktiskt när arvtagare måste implementera flera kontrakt samtidigt. Till exempel kan en UI-händelse vara både klickbar och spårbar. Med sealed class skulle man behöva välja en basklass, med sealed interface implementerar arvtagaren båda.

Begränsningar för sealed class

Sealed class är en klass, så varje arvtagare kan bara ha en förälder. Sealed interface löser detta problem, men kan inte innehålla tillstånd. Valet mellan dem beror på uppgiften: gemensam logik med fält behövs — sealed class, flexibilitet i kontrakt behövs — sealed interface.

kotlin
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>
}

// Arvtagaren implementerar båda gränssnitten
data class LoginClicked(
    override val name: String = "login_click",
    override val params: Map<String, Any> = emptyMap()
) : ScreenEvent, AnalyticsEvent

Sealed Class för felhierarki inom mobilutveckling

En av de viktigaste tillämpningarna av sealed class inom mobilutveckling — typsäker felhierarki. Istället för att kasta undantag av olika typer eller använda allmänt Exception, samlar sealed class alla möjliga domänfel i en typ.

Hur man bygger en felhierarki

Skapa en sealed class DomainError och lista alla typer av fel som arvtagare. Varje arvtagare innehåller endast de data som är meningsfulla för den feltypen. Kompilatorn garanterar att du vid felhantering inte kommer att glömma någon variant.

Exempel: hantering av autentiseringsfel

Betrakta en applikation med auktorisering, där olika fel scenarier är möjliga: felaktigt lösenord, kontoblockering, serverproblem. Sealed class förenar dem i en enda typ med uttömmande hantering.

kotlin
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 ->
        "Återstående försök: ${3 - error.attempts}"
    is AuthError.AccountBlocked ->
        "Åtkomst blockerad till ${Date(error.until)}"
    is AuthError.NetworkFailure ->
        "Kontrollera anslutningen: ${error.cause.localizedMessage}"
    AuthError.ServerError ->
        "Servern är tillfälligt otillgänglig"
}

Användningsmönster för Sealed Class i Android

Sealed class har blivit ett standardverktyg i arkitekturen för Android-applikationer. Låt oss titta på tre viktiga mönster där sealed class är oumbärlig inom mobilutveckling.

  • UI State — representation av skärmen som en ändlig tillståndsmaskin: Loading, Content, Error. Varje tillstånd innehåller sina egna data, och sealed class garanterar att alla övergångar har bearbetats.
  • Navigation Event — sealed class istället för navigationskonstanter: varje skärm är en separat arvtagare med ruttparametrar. Kompilatorn kontrollerar argumenttyperna.
  • Action/Intent — mönstret Unidirectional Data Flow använder sealed class för att representera alla åtgärder som användaren kan utföra på skärmen.

Separat är det värt att nämna tillämpningen av sealed class i Clean Architecture. Varje lager (data, domain, presentation) använder sealed class för sina felttyper, och mappare omvandlar en sealed class till en annan. Till exempel mappas DataError från datalagret till DomainError för affärslogik och sedan till UiState för presentationslagret. Detta bevarar typsäkerheten på alla nivåer i applikationen och garanterar att inget fel förblir obearbetat.

Testning av sealed class hierarkier

Testning av sealed class kräver ett speciellt tillvägagångssätt, eftersom varje arvtagare är en separat typ med eget tillstånd. Det rekommenderas att skriva parameteriserade tester som går igenom alla arvtagare av sealed class. Detta garanterar att when-uttryck täcker alla varianter, inklusive nya som lagts till vid utökning av hierarkin.

För UI-tester gör sealed class som UiState det möjligt att kontrollera visningen av varje tillstånd: Loading visar en spinner, Content — data, Error — ett felmeddelande. Eftersom sealed class är ändlig ger testtäckning av alla tillstånd fullständig säkerhet om UI-logikens korrekthet.

Vanliga misstag vid arbete med Sealed Class

Trots konceptets enkelhet gör utvecklare regelbundet misstag vid utformning av sealed class hierarkier. Låt oss titta på de viktigaste problemen och hur man undviker dem.

  • Arvtagare i olika filer — kompilatorn tillåter inte att deklarera sealed class om arvtagarna finns utanför filen. Denna begränsning garanterar uttömmande when.
  • Blandning av sealed och open — sealed class kan inte vara open samtidigt. Om en utbyggbar hierarki behövs, använd en vanlig abstract class, men du offrar exhaustiveness.
  • Överdriven nästling — sealed class i sealed class skapar en djup hierarki som är svår att underhålla. För enkla scenarier räcker två nivåer.
  • Glömd else i when — om sealed class från ett bibliotek saknar exhaustiveness, varnar inte kompilatorn om en missad gren. Lägg till endast medvetet till else.

Vanliga frågor

Kan sealed class ha abstrakta metoder?

Ja, sealed class kan innehålla abstrakta metoder, och varje arvtagare måste implementera dem. Detta är praktiskt när alla varianter ska tillhandahålla ett enhetligt gränssnitt, men med olika exekveringslogik.

Finns sealed class tillgängliga i Java?

I Java 17+ har förseglade klasser och gränssnitt med modifieraren sealed dykt upp. Android stöder för närvarande Java 17 delvis, men i Kotlin-projekt är sealed class tillgänglig från Kotlin 1.0 utan begränsningar.

Kan en sealed class ärva från en annan sealed class?

Ja, en sealed class kan vara arvtagare till en annan. Sealed class hierarkin förblir ändlig: kompilatorn känner till alla arvtagare på varje nivå. Detta möjliggör byggande av detaljerade felklassificeringar.

Påverkar sealed class prestandan?

Sealed class skapar ingen overhead vid körning. Kompilatorn optimerar when-uttryck med sealed class till övergångstabeller (tableswitch), vilket är snabbare än if-else-kedjor. Prestandan är identisk med enum.

Hur testar man sealed class hierarkier?

Varje arvtagare till sealed class testas separat. Eftersom sealed class är ändlig kan ett parameteriserat test skrivas som går igenom alla varianter. Detta ger fullständig täckning av grenarna i when-block.

Sammanfattning

  • Sealed class — klass med en fast uppsättning arvtagare deklarerade i en fil, vilket ger uttömmande when-analys vid kompilering.
  • Varje arvtagare till sealed class kan ha sin egen datastruktur — den huvudsakliga skillnaden från enum, där alla varianter är konstanter av samma typ.
  • Sealed interface (Kotlin 1.5+) stöder multipelt arv, sealed class — endast enkelt arv. Valet beror på behovet av delat tillstånd.
  • Sealed class — standardmekanism för typsäker felhierarki i Kotlin: varje felt typ är en separat arvtagare med relevanta fält.
  • Huvudmönster i Android: UI State, Navigation Event och Action/Intent — byggda på sealed class för garanti av fullständig bearbetning.
  • Undvik arvtagare i olika filer, överdriven nästling och blandning av sealed med open — detta bryter kontraktet för den ändliga hierarkin.

Vi utvecklar en mobil applikation nyckelfärdigt

IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.

Diskutera projektet

Läs också