---
title: "Sealed Class em Kotlin: O que É e Como Funciona | Kotlin Brasil"
url: "https://kotlin.dev.br/glossario/sealed-class/"
markdown_url: "https://kotlin.dev.br/glossario/sealed-class.MD"
description: "Descubra o que é Sealed Class em Kotlin, como criar hierarquias restritas de tipos e usar com when de forma segura."
date: "2026-02-03"
author: "Karina Melo"
---

# Sealed Class em Kotlin: O que É e Como Funciona | Kotlin Brasil

Descubra o que é Sealed Class em Kotlin, como criar hierarquias restritas de tipos e usar com when de forma segura.


## O que é Sealed Class em Kotlin?

Uma `sealed class` em Kotlin define uma **hierarquia restrita de tipos**. Isso significa que todas as subclasses possíveis são conhecidas em tempo de compilação. É como um enum turbinado — cada subtipo pode ter propriedades e comportamentos diferentes.

A grande vantagem é que, ao usar `when`, o compilador sabe exatamente quais são os casos possíveis e avisa se você esquecer algum.

### Sintaxe básica

```kotlin
sealed class Resultado {
    data class Sucesso(val dados: String) : Resultado()
    data class Erro(val mensagem: String, val codigo: Int) : Resultado()
    object Carregando : Resultado()
}
```

Cada subclasse pode ter seus próprios campos e lógica. Diferente de um `enum`, onde cada valor é uma instância única, aqui cada subtipo pode carregar dados distintos.

### Usando com `when`

A mágica acontece quando você combina sealed class com `when`:

```kotlin
fun tratarResultado(resultado: Resultado): String {
    return when (resultado) {
        is Resultado.Sucesso -> "Deu certo: ${resultado.dados}"
        is Resultado.Erro -> "Erro ${resultado.codigo}: ${resultado.mensagem}"
        is Resultado.Carregando -> "Aguarde..."
    }
}
```

Repare que não precisa de `else`. O compilador sabe que esses são todos os casos possíveis. Se amanhã você adicionar um novo subtipo, o compilador vai apontar todos os lugares onde falta tratar o novo caso.

### Exemplo prático com estado de tela

```kotlin
sealed class EstadoTela {
    object Inicial : EstadoTela()
    data class Conteudo(val itens: List<String>) : EstadoTela()
    data class FalhaConexao(val tentativas: Int) : EstadoTela()
}

fun renderizar(estado: EstadoTela) {
    when (estado) {
        is EstadoTela.Inicial -> println("Carregando tela inicial...")
        is EstadoTela.Conteudo -> println("Exibindo ${estado.itens.size} itens")
        is EstadoTela.FalhaConexao -> println("Falha! Tentativa ${estado.tentativas}")
    }
}
```

### Sealed class com comportamento

As subclasses de uma sealed class podem ter métodos próprios e até implementar interfaces diferentes:

```kotlin
sealed class Pagamento {
    abstract fun processar(): String

    data class CartaoCredito(
        val numero: String,
        val parcelas: Int
    ) : Pagamento() {
        override fun processar(): String {
            val ultimosDigitos = numero.takeLast(4)
            return "Cartão ****$ultimosDigitos em ${parcelas}x"
        }
    }

    data class Pix(val chave: String) : Pagamento() {
        override fun processar(): String {
            return "PIX para chave $chave"
        }
    }

    data class Boleto(val codigoBarras: String, val vencimento: String) : Pagamento() {
        override fun processar(): String {
            return "Boleto com vencimento em $vencimento"
        }
    }

    object Dinheiro : Pagamento() {
        override fun processar() = "Pagamento em dinheiro"
    }
}

fun finalizarCompra(pagamento: Pagamento) {
    println("Processando: ${pagamento.processar()}")
}

fun main() {
    finalizarCompra(Pagamento.CartaoCredito("1234567890123456", 3))
    finalizarCompra(Pagamento.Pix("karina@email.com"))
    finalizarCompra(Pagamento.Boleto("12345.67890", "2026-04-15"))
    finalizarCompra(Pagamento.Dinheiro)
}
```

### Sealed interface (Kotlin 1.5+)

A partir do Kotlin 1.5, você pode usar `sealed interface` para criar hierarquias seladas com mais flexibilidade, permitindo que uma classe implemente múltiplas sealed interfaces:

```kotlin
sealed interface Erro {
    val mensagem: String
}

sealed interface Recuperavel {
    fun tentar(): Boolean
}

data class ErroDeRede(
    override val mensagem: String,
    val codigo: Int
) : Erro, Recuperavel {
    override fun tentar(): Boolean {
        println("Tentando reconexão...")
        return codigo != 404
    }
}

data class ErroDeValidacao(
    override val mensagem: String,
    val campo: String
) : Erro {
    // Não é recuperável
}

fun tratarErro(erro: Erro) {
    println("Erro: ${erro.mensagem}")
    if (erro is Recuperavel) {
        val sucesso = erro.tentar()
        println("Recuperação: ${if (sucesso) "OK" else "falhou"}")
    }
}
```

### Quando usar?

Sealed classes são ideais para modelar **estados finitos**: resultados de operações, estados de UI, eventos de navegação e respostas de rede. Sempre que você tiver um conjunto fechado de possibilidades, pense em sealed class.

### Casos de Uso no Mundo Real

- **Gerenciamento de estado de UI**: em aplicações Android com MVVM ou MVI, sealed classes representam os diferentes estados da tela (carregando, sucesso, erro), garantindo que todos os estados sejam tratados na camada de apresentação.
- **Resultado de operações de rede**: modelar respostas HTTP como `Sucesso(dados)`, `Erro(código, mensagem)` e `SemConexao`, forçando o tratamento de todos os cenários possíveis.
- **Eventos de navegação**: representar destinos e ações de navegação como subtipos selados, garantindo que rotas novas sejam tratadas em todo o código de navegação.
- **Processamento de comandos**: em arquiteturas orientadas a eventos, sealed classes representam os diferentes comandos que um sistema pode receber, com o compilador garantindo que nenhum comando fique sem tratamento.

### Boas Práticas

- Use `object` para subtipos sem dados (como `Carregando` ou `Vazio`) e `data class` para subtipos que carregam informações. Isso aproveita ao máximo os recursos do Kotlin.
- Prefira `sealed interface` quando precisar que uma classe participe de múltiplas hierarquias seladas. Sealed interfaces são mais flexíveis que sealed classes.
- Evite o branch `else` em expressões `when` com sealed classes. O `else` esconde a adição de novos subtipos, anulando a principal vantagem da sealed class.
- Mantenha a hierarquia selada no mesmo arquivo ou pacote (desde Kotlin 1.5, subclasses podem estar no mesmo pacote). Isso facilita a visualização de todos os casos possíveis.
- Use sealed classes para modelar domínio, não para lógica de infraestrutura. Elas brilham quando representam conceitos do negócio com um conjunto finito de variações.

### Erros Comuns

- **Adicionar `else` no `when`**: ao usar `else`, o compilador não avisa quando um novo subtipo é adicionado. Isso elimina a principal vantagem de usar sealed class e pode causar bugs silenciosos.
- **Criar hierarquias muito profundas**: sealed classes dentro de sealed classes criam complexidade desnecessária. Mantenha a hierarquia plana sempre que possível.
- **Confundir sealed class com enum**: enums são para valores fixos e simples (como dias da semana). Sealed classes são para tipos com dados e comportamentos diferentes. Usar enum quando precisa de sealed class limita o modelo.
- **Esquecer de tratar novos subtipos**: ao adicionar um novo subtipo à sealed class, todos os `when` sem `else` vão parar de compilar. Isso é uma vantagem, não um problema. Trate cada caso conscientemente.
- **Definir subclasses fora do pacote**: subclasses de sealed classes devem estar no mesmo pacote (módulo, até Kotlin 1.4). Definir fora causa erro de compilação e frustra o propósito da restrição.

### Perguntas Frequentes

**Qual a diferença entre sealed class e enum?** Enums têm um número fixo de instâncias, e cada instância é um singleton. Sealed classes permitem múltiplas instâncias de cada subtipo, e cada subtipo pode ter propriedades e construtores diferentes. Use enum para valores simples e sealed class para tipos complexos.

**Posso herdar de uma sealed class fora do mesmo módulo?** Não. Todas as subclasses de uma sealed class devem estar no mesmo módulo de compilação (e no mesmo pacote a partir do Kotlin 1.5). Essa restrição é o que permite ao compilador conhecer todos os subtipos em tempo de compilação.

**Sealed class pode ter construtor?** Sim. Sealed classes podem ter construtores com parâmetros, e as subclasses precisam chamá-los. Porém, o construtor de uma sealed class é sempre `protected` por padrão (ou `private`).

**Quando usar sealed interface em vez de sealed class?** Use `sealed interface` quando precisar que um tipo implemente múltiplas hierarquias seladas (herança múltipla de interfaces). Use `sealed class` quando quiser compartilhar estado ou implementação entre os subtipos.

### Termos Relacionados

- [Object](/glossario/object) — usado como subtipo de sealed class quando não há dados associados
- [Data Class](/glossario/data-class) — o tipo mais comum de subtipo em hierarquias seladas
- [Enum](/glossario/enum) — alternativa mais simples para conjuntos fixos de valores
- [When](/glossario/when) — expressão que se beneficia diretamente da exaustividade de sealed classes
- [Interface](/glossario/interface) — base para sealed interfaces introduzidas no Kotlin 1.5
