Sobes.tech
Middle

Qual é a diferença entre classes sealed e classes abstratas em Kotlin?

sobes.tech IA

Resposta da IA

A principal diferença entre classes sealed e abstratas é que as classes sealed limitam a hierarquia de herança a um único arquivo ou módulo (para Kotlin 1.5+). Os herdeiros de uma classe sealed devem ser declarados no mesmo arquivo que a própria classe sealed, garantindo uma verificação exaustiva ao usar expressões when.

Diferenças:

  • Herança:
    • Classes abstratas podem ser herdadas em qualquer lugar do projeto.
    • Classes sealed só podem ser herdadas dentro do mesmo arquivo (antes do Kotlin 1.5) ou dentro do mesmo módulo (com Kotlin 1.5+).
  • Uso com when:
    • Ao usar when com um tipo sealed, o compilador pode verificar se todos os subtipos possíveis foram considerados, tornando when exaustivo e eliminando a necessidade de especificar explicitamente um ramo else se todos os subtipos forem tratados.
    • Com classes abstratas, o compilador não pode garantir a exaustividade, portanto, um else geralmente é necessário.
  • Criação de instâncias:
    • Nem classes abstratas nem sealed podem ser instanciadas diretamente.
  • Membros:
    • Tanto classes abstratas quanto sealed podem ter membros abstratos e não abstratos.

Exemplo de classe sealed:

sealed class Result<out T> {
    data class Success<out T>(val data: T) : Result<T>()
    data class Error(val message: String) : Result<Nothing>()
}

fun processResult(result: Result<Int>) {
    when (result) {
        is Result.Success -> {
            // Processar resultado bem-sucedido
            println("Sucesso: ${result.data}")
        }
        is Result.Error -> {
            // Processar erro
            println("Erro: ${result.message}")
        }
        // Não é necessário else se todos os herdeiros forem tratados
    }
}

Exemplo de classe abstrata:

abstract class Shape {
    abstract fun area(): Double
}

class Circle(val radius: Double) : Shape() {
    override fun area(): Double = Math.PI * radius * radius
}

class Rectangle(val width: Double, val height: Double) : Shape() {
    override fun area(): Double = width * height
}

fun calculateArea(shape: Shape): Double {
    return shape.area()
}

Quando usar:

  • Classes sealed: Ideais para representar um conjunto limitado de estados ou tipos possíveis, quando você precisa de uma verificação exaustiva em expressões when. Frequentemente usados para modelar resultados de operações (sucesso/erro), estados de UI, eventos.
  • Classes abstratas: Adequadas para definir funcionalidades gerais e contratos para um grupo de classes relacionadas, que podem ser herdadas em qualquer parte do projeto.

Resumindo, classes sealed fornecem um controle mais rigoroso sobre a hierarquia de herança e melhoram a segurança e legibilidade do código ao lidar com um conjunto limitado de subtipos.