Sealed Class — co to je, princip fungování a použití

Autor: IT Sectr Publikováno: 2026-05-26 Doba čtení: 8 min

Sealed Class — speciální typ třídy v Kotlinu, který omezuje hierarchii dědičnosti na pevnou sadu podtypů. Všichni dědicové jsou deklarováni ve stejném souboru a jsou známí kompilátoru, což umožňuje použití vyčerpávajícího bloku when bez povinné else větve. Podle Kotlin Docs, 2026 jsou zapečetěné třídy klíčovým mechanismem pro reprezentaci omezených hierarchií, jako jsou stavy, typy chyb a události UI.

Hlavní body

  • Sealed Class — třída s pevnou sadou dědiců deklarovaných ve stejném souboru.
  • Exhaustive when — kompilátor kontroluje, že všechny podtypy byly zpracovány, čímž eliminuje zapomenuté else větve.
  • Sealed interface — Kotlin 1.5+ podporuje zapečetěné rozhraní pro vícenásobnou dědičnost.
  • Hierarchie chyb — sealed class je standardní způsob typově bezpečného zpracování chyb v Kotlinu.
  • Rozdíl od enum — každý dědic sealed class může obsahovat jedinečný stav a různý počet polí.

Co je Sealed Class?

Sealed Class (zapečetěná třída) — je třída v Kotlinu označená modifikátorem sealed. Definuje omezenou hierarchii typů: všichni možní dědicové jsou uvedeni ve stejném souboru a kompilátor o každém z nich ví. To odlišuje sealed class od běžné otevřené třídy, jejíž dědicové mohou být deklarováni kdekoli.

Hlavním účelem sealed class je typově bezpečná reprezentace konečné sady variant. Každý dědic může mít vlastní datovou strukturu, což činí sealed class flexibilnější než enum. Za běhu je sealed class běžná abstraktní třída, kompilátor ukládá omezení pouze ve fázi kompilace.

Sealed class je zvláště užitečný v architektuře Android aplikací: stavy UI, výsledky síťových požadavků, události navigace typu Intent a samozřejmě hierarchie chyb — typické scénáře použití.

Při kompilaci je sealed class optimalizován do přechodové tabulky pro výrazy when, což jej činí výkonnějším než řetězce if-else. V kombinaci s data class může každý dědic obsahovat nejen stav, ale také metody, což umožňuje vytvářet samodokumentující doménové modely bez boilerplate kódu.

Sealed class je také účinný pro reprezentaci konečných automatů (state machine) v mobilních aplikacích. Každý stav — samostatný dědic s jedinečnými parametry a přechody mezi stavy jsou řízeny prostřednictvím výrazu when. Kompilátor zaručuje, že všechny možné stavy byly zpracovány, což eliminuje chyby za běhu při změně stavu UI nebo obchodní logiky.

Sealed Class a Enum: klíčové rozdíly

Začínající vývojáři v Kotlinu často zaměňují sealed class s enum, protože oba omezují sadu hodnot. Mezi nimi je však zásadní rozdíl: enum — je sada konstant stejného typu, sealed class — hierarchie různých typů.

Kdy zvolit enum

Enum je optimální, když všechny varianty jsou konstanty bez další struktury. Například dny v týdnu, stavy objednávky nebo typy akcí bez parametrů. Každá hodnota enum je singleton s pevným názvem.

Kdy zvolit sealed class

Sealed class je potřeba, když každá varianta má vlastní data. Například chyba sítě obsahuje kód odpovědi, chyba parsování — podrobnosti a chyba autorizace — zprávu. Každý dědic sealed class je samostatný typ s jedinečnými poli.

kotlin
// Enum — všechny varianty jednoho typu
enum class Status { LOADING, SUCCESS, ERROR }

// Sealed class — každá varianta s vlastními daty
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 versus Sealed Class

Od Kotlin 1.5 existuje možnost deklarovat sealed interface. To rozšiřuje koncept sealed na rozhraní: sealed interface má také pevnou sadu implementací, ale podporuje vícenásobnou dědičnost.

Kdy použít sealed interface

Sealed interface je vhodný, když dědicové musí implementovat více kontraktů současně. Například událost UI může být současně klikatelná a sledovatelná. U sealed class byste museli vybrat jednu základní třídu, u sealed interface dědic implementuje obě.

Omezení sealed class

Sealed class je třída, takže každý dědic může mít pouze jednoho rodiče. Sealed interface tento problém řeší, ale nemůže obsahovat stav. Volba mezi nimi závisí na úkolu: potřebujete společnou logiku s poli — sealed class, potřebujete flexibilitu kontraktů — 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>
}

// Dědic implementuje obě rozhraní
data class LoginClicked(
    override val name: String = "login_click",
    override val params: Map<String, Any> = emptyMap()
) : ScreenEvent, AnalyticsEvent

Sealed Class pro hierarchii chyb v mobilním vývoji

Jedno z hlavních použití sealed class v mobilním vývoji — typově bezpečná hierarchie chyb. Místo vyhazování výjimek různých typů nebo používání obecného Exception, sealed class shromažďuje všechny možné doménové chyby do jednoho typu.

Jak vybudovat hierarchii chyb

Vytvořte sealed class DomainError a vyjmenujte všechny typy selhání jako dědice. Každý dědic obsahuje pouze data, která mají význam pro daný typ chyby. Kompilátor zaručuje, že při zpracování chyby nezapomenete žádnou variantu.

Příklad: zpracování chyb autentizace

Uvažujme aplikaci s autorizací, kde jsou možné různé scénáře selhání: nesprávné heslo, blokace účtu, problém se serverem. Sealed class je spojuje do jednoho typu s vyčerpávajícím zpracováním.

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 ->
        "Zbývá pokusů: ${3 - error.attempts}"
    is AuthError.AccountBlocked ->
        "Přístup zablokován do ${Date(error.until)}"
    is AuthError.NetworkFailure ->
        "Zkontrolujte připojení: ${error.cause.localizedMessage}"
    AuthError.ServerError ->
        "Server je dočasně nedostupný"
}

Vzory použití Sealed Class v Androidu

Sealed class se stal standardním nástrojem v architektuře aplikací pro Android. Podívejme se na tři klíčové vzory, kde je sealed class v mobilním vývoji nepostradatelný.

  • UI State — reprezentace obrazovky jako konečného automatu: Loading, Content, Error. Každý stav obsahuje svá data a sealed class zaručuje, že všechny přechody jsou zpracovány.
  • Navigation Event — sealed class místo navigačních konstant: každá obrazovka je samostatný dědic s parametry trasy. Kompilátor kontroluje typy argumentů.
  • Action/Intent — vzor Unidirectional Data Flow používá sealed class k reprezentaci všech akcí, které může uživatel na obrazovce provést.

Samostatně stojí za zmínku použití sealed class v Clean Architecture. Každá vrstva (data, domain, presentation) používá sealed class pro své typy chyb a mappery převádějí jeden sealed class na druhý. Například DataError z datové vrstvy je mapován na DomainError pro obchodní logiku a poté na UiState pro prezentační vrstvu. To zachovává typovou bezpečnost na všech úrovních aplikace a zaručuje, že žádná chyba nezůstane nezpracována.

Testování hierarchií sealed class

Testování sealed class vyžaduje zvláštní přístup, protože každý dědic je samostatný typ s vlastním stavem. Doporučuje se psát parametrizované testy, které procházejí všechny dědice sealed class. To zaručuje, že výrazy when pokrývají všechny varianty, včetně nových přidaných při rozšiřování hierarchie.

Pro UI testy sealed class jako UiState umožňuje kontrolu zobrazení každého stavu: Loading ukazuje spinner, Content — data, Error — chybovou zprávu. Protože je sealed class konečný, testovací pokrytí všech stavů dává plnou jistotu správnosti UI logiky.

Typické chyby při práci se Sealed Class

Navzdory jednoduchosti konceptu vývojáři pravidelně dělají chyby při navrhování hierarchií sealed class. Podívejme se na hlavní problémy a způsoby, jak se jim vyhnout.

  • Dědicové v různých souborech — kompilátor nepovolí deklarovat sealed class, pokud jsou dědicové mimo soubor. Toto omezení zaručuje vyčerpávající when.
  • Míchání sealed a open — sealed class nemůže být současně open. Pokud potřebujete rozšiřitelnou hierarchii, použijte běžný abstract class, ale obětujete exhaustivitu.
  • Nadměrné vnoření — sealed class do sealed class vytváří hlubokou hierarchii, kterou je obtížné udržovat. Pro jednoduché scénáře stačí dvě úrovně.
  • Zapomenutý else ve when — pokud sealed class z knihovny nemá exhaustivitu, kompilátor neupozorní na vynechanou větev. Else přidávejte pouze vědomě.

Často kladené otázky

Může sealed class mít abstraktní metody?

Ano, sealed class může obsahovat abstraktní metody a každý dědic je povinen je implementovat. To je užitečné, když všechny varianty musí poskytovat jednotné rozhraní, ale s odlišnou logikou provedení.

Jsou sealed class dostupné v Javě?

V Java 17+ se objevily zapečetěné třídy a rozhraní s modifikátorem sealed. Android zatím podporuje Java 17 částečně, ale v Kotlin projektech je sealed class dostupný od Kotlin 1.0 bez omezení.

Může sealed class dědit z jiného sealed class?

Ano, jeden sealed class může být dědicem druhého. Hierarchie sealed class zůstává konečná: kompilátor zná všechny dědice na každé úrovni. To umožňuje vytvářet podrobné klasifikace chyb.

Ovlivňuje sealed class výkon?

Sealed class nevytváří režii za běhu. Kompilátor optimalizuje výrazy when s sealed class do přechodových tabulek (tableswitch), což je rychlejší než řetězce if-else. Výkon je identický s enum.

Jak testovat hierarchie sealed class?

Každý dědic sealed class se testuje samostatně. Protože je sealed class konečný, lze napsat parametrizovaný test, který prochází všechny varianty. To poskytuje úplné pokrytí větví bloků when.

Shrnutí

  • Sealed class — třída s pevnou sadou dědiců deklarovaných v jednom souboru, poskytující vyčerpávající when analýzu při kompilaci.
  • Každý dědic sealed class může mít vlastní datovou strukturu — hlavní rozdíl od enum, kde všechny varianty jsou konstanty stejného typu.
  • Sealed interface (Kotlin 1.5+) podporuje vícenásobnou dědičnost, sealed class — pouze jednoduchou. Volba závisí na potřebě sdíleného stavu.
  • Sealed class — standardní mechanismus pro typově bezpečnou hierarchii chyb v Kotlinu: každý typ selhání je samostatný dědic s relevantními poli.
  • Hlavní vzory v Androidu: UI State, Navigation Event a Action/Intent — jsou postaveny na sealed class pro zaručení úplnosti zpracování.
  • Vyhněte se dědicům v různých souborech, nadměrnému vnoření a míchání sealed s open — to porušuje kontrakt konečné hierarchie.

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také