Sobes.tech
Middle

¿Cuál es la diferencia entre las clases selladas y las clases abstractas en Kotlin?

sobes.tech AI

Respuesta de la IA

La principal diferencia entre las clases selladas y las abstractas es que las clases selladas limitan la jerarquía de herencia dentro de un mismo archivo o módulo (para Kotlin 1.5+). Los herederos de una clase sellada deben ser declarados en el mismo archivo que la clase sellada, lo que garantiza una comprobación exhaustiva al usar expresiones when.

Diferencias:

  • Herencia:
    • Las clases abstractas pueden ser heredadas en cualquier parte del proyecto.
    • Las clases selladas solo pueden ser heredadas dentro del mismo archivo (antes de Kotlin 1.5) o dentro del mismo módulo (con Kotlin 1.5+).
  • Uso con when:
    • Al usar when con un tipo sellado, el compilador puede verificar que todos los subtipos posibles han sido considerados, haciendo que when sea exhaustivo y eliminando la necesidad de especificar explícitamente una rama else si todos los subtipos están manejados.
    • Con clases abstractas, el compilador no puede garantizar la exhaustividad, por lo que a menudo se requiere un else.
  • Creación de instancias:
    • Ni las clases abstractas ni las selladas pueden ser instanciadas directamente.
  • Miembros:
    • Tanto las clases abstractas como las selladas pueden tener miembros abstractos y no abstractos.

Ejemplo de clase sellada:

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 -> {
            // Procesar resultado exitoso
            println("Éxito: ${result.data}")
        }
        is Result.Error -> {
            // Procesar error
            println("Error: ${result.message}")
        }
        // No se requiere else si todos los herederos están manejados
    }
}

Ejemplo de clase abstracta:

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()
}

Cuándo usar:

  • Clases selladas: Ideales para representar un conjunto limitado de estados o tipos posibles, cuando necesitas una comprobación exhaustiva en expresiones when. Se usan frecuentemente para modelar resultados de operaciones (éxito/error), estados de UI, eventos.
  • Clases abstractas: Adecuadas para definir funcionalidades y contratos comunes para un grupo de clases relacionadas que pueden ser heredadas en cualquier parte del proyecto.

En resumen, las clases selladas ofrecen un control más estricto sobre la jerarquía de herencia y mejoran la seguridad y legibilidad del código al manejar un conjunto limitado de subtipos.