Sealed Class — qué es, principio de funcionamiento y aplicación

Autor: IT Sectr Publicado: 2026-05-26 Tiempo de lectura: 8 min

Sealed Class es un tipo especial de clase en Kotlin que limita la jerarquía de herencia a un conjunto fijo de subtipos. Todos los subtipos se declaran en el mismo archivo y el compilador los conoce, lo que permite usar un bloque when exhaustivo sin una rama else obligatoria. Según Kotlin Docs, 2026, las clases selladas son un mecanismo clave para representar jerarquías limitadas, como estados, tipos de error y eventos de UI.

Puntos clave

  • Sealed Class — clase con un conjunto fijo de subtipos declarados en el mismo archivo.
  • Exhaustive when — el compilador verifica que se hayan manejado todos los subtipos, eliminando ramas else olvidadas.
  • Sealed interface — Kotlin 1.5+ admite interfaces selladas para herencia múltiple.
  • Jerarquía de errores — sealed class es la forma estándar de manejo de errores con seguridad de tipos en Kotlin.
  • Diferencia de enum — cada subtipo de sealed class puede contener estado único y diferente cantidad de campos.

¿Qué es Sealed Class?

Sealed Class (clase sellada) es una clase en Kotlin marcada con el modificador sealed. Define una jerarquía de tipos limitada: todos los subtipos posibles se enumeran en el mismo archivo y el compilador conoce cada uno de ellos. Esto diferencia a sealed class de una clase abierta normal cuyos subtipos pueden declararse en cualquier lugar.

El propósito principal de sealed class es la representación con seguridad de tipos de un conjunto finito de variantes. Cada subtipo puede tener su propia estructura de datos, lo que hace que sealed class sea más flexible que enum. En tiempo de ejecución, sealed class es una clase abstracta normal; el compilador impone restricciones solo en tiempo de compilación.

Sealed class es especialmente útil en la arquitectura de aplicaciones Android: estados de UI, resultados de solicitudes de red, eventos de navegación similares a Intents y, por supuesto, jerarquías de errores son casos de uso típicos.

En tiempo de compilación, sealed class se optimiza en una tabla de saltos para expresiones when, lo que la hace más eficiente que las cadenas if-else. Combinada con data class, cada subtipo puede contener no solo estado sino también métodos, lo que permite crear modelos de dominio autodocumentados sin código boilerplate.

Sealed class también es eficaz para representar máquinas de estado en aplicaciones móviles. Cada estado es un subtipo separado con parámetros únicos, y las transiciones entre estados se controlan mediante expresiones when. El compilador garantiza que todos los estados posibles sean manejados, eliminando errores en tiempo de ejecución al cambiar el estado de la UI o la lógica de negocio.

Sealed Class vs Enum: diferencias clave

Los desarrolladores principiantes de Kotlin a menudo confunden sealed class con enum, ya que ambos restringen el conjunto de valores. Sin embargo, existe una diferencia fundamental: enum es un conjunto de constantes del mismo tipo, mientras que sealed class es una jerarquía de tipos diferentes.

Cuándo elegir enum

Enum es óptimo cuando todas las variantes son constantes sin estructura adicional. Por ejemplo, días de la semana, estados de pedido o tipos de acciones sin parámetros. Cada valor de enum es un singleton con un nombre fijo.

Cuándo elegir sealed class

Sealed class es necesaria cuando cada variante tiene sus propios datos. Por ejemplo, un error de red contiene un código de respuesta, un error de análisis contiene detalles, y un error de autorización contiene un mensaje. Cada subtipo de sealed class es un tipo separado con campos únicos.

kotlin
// Enum — todas las variantes de un mismo tipo
enum class Status { LOADING, SUCCESS, ERROR }

// Sealed class — cada variante con sus propios datos
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 vs Sealed Class

Desde Kotlin 1.5, es posible declarar sealed interface. Esto extiende el concepto de sellado a las interfaces: una sealed interface también tiene un conjunto fijo de implementaciones, pero admite herencia múltiple.

Cuándo usar sealed interface

Sealed interface es conveniente cuando los subtipos necesitan implementar varios contratos simultáneamente. Por ejemplo, un evento de UI puede ser a la vez cliqueable y rastreable. Con sealed class, tendrías que elegir una clase base; con sealed interface, el subtipo implementa ambos.

Limitaciones de sealed class

Sealed class es una clase, por lo que cada subtipo solo puede tener un padre. Sealed interface resuelve este problema pero no puede contener estado. La elección entre ellos depende de la tarea: si se necesita lógica compartida con campos — usa sealed class; si se necesita flexibilidad de contratos — usa 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>
}

// El subtipo implementa ambas interfaces
data class LoginClicked(
    override val name: String = "login_click",
    override val params: Map<String, Any> = emptyMap()
) : ScreenEvent, AnalyticsEvent

Sealed Class para jerarquías de errores en desarrollo móvil

Uno de los usos principales de sealed class en el desarrollo móvil son las jerarquías de errores con seguridad de tipos. En lugar de lanzar excepciones de diferentes tipos o usar una Exception general, sealed class reúne todos los errores posibles del dominio en un solo tipo.

Cómo construir una jerarquía de errores

Crea una sealed class DomainError y enumera todos los tipos de fallo como subtipos. Cada subtipo contiene solo los datos relevantes para ese tipo de error en particular. El compilador garantiza que al manejar el error no olvidarás ninguna variante.

Ejemplo: manejo de errores de autenticación

Considera una aplicación con autorización donde son posibles diferentes escenarios de fallo: contraseña incorrecta, cuenta bloqueada, problema con el servidor. Sealed class los combina en un solo tipo con manejo exhaustivo.

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 ->
        "Intentos restantes: ${3 - error.attempts}"
    is AuthError.AccountBlocked ->
        "Acceso bloqueado hasta ${Date(error.until)}"
    is AuthError.NetworkFailure ->
        "Verifique la conexión: ${error.cause.localizedMessage}"
    AuthError.ServerError ->
        "Servidor temporalmente no disponible"
}

Patrones de uso de Sealed Class en Android

Sealed class se ha convertido en una herramienta estándar en la arquitectura de aplicaciones Android. Veamos tres patrones clave donde sealed class es indispensable en el desarrollo móvil.

  • UI State — representación de la pantalla como una máquina de estados: Loading, Content, Error. Cada estado contiene sus propios datos, y sealed class garantiza que todas las transiciones sean manejadas.
  • Navigation Event — sealed class en lugar de constantes de navegación: cada pantalla es un subtipo separado con parámetros de ruta. El compilador verifica los tipos de argumentos.
  • Action/Intent — el patrón Unidirectional Data Flow usa sealed class para representar todas las acciones que un usuario puede realizar en una pantalla.

También cabe destacar el uso de sealed class en Clean Architecture. Cada capa (data, domain, presentation) usa sealed class para sus tipos de error, y los mappers convierten una sealed class en otra. Por ejemplo, DataError de la capa de datos se mapea a DomainError para la lógica de negocio, y luego a UiState para la capa de presentación. Esto preserva la seguridad de tipos en todos los niveles de la aplicación y garantiza que ningún error quede sin manejar.

Pruebas de jerarquías de Sealed Class

Las pruebas de sealed class requieren un enfoque especial, ya que cada subtipo es un tipo separado con su propio estado. Se recomienda escribir pruebas parametrizadas que iteran sobre todos los subtipos de sealed class. Esto garantiza que las expresiones when cubran todas las variantes, incluidas las nuevas añadidas al extender la jerarquía.

Para las pruebas de UI, sealed class como UiState permite verificar la visualización de cada estado: Loading muestra un spinner, Content muestra datos, Error muestra un mensaje de error. Dado que sealed class es finito, la cobertura de pruebas de todos los estados brinda total confianza en la corrección de la lógica de UI.

Errores típicos al trabajar con Sealed Class

A pesar de la simplicidad del concepto, los desarrolladores cometen errores regularmente al diseñar jerarquías de sealed class. Veamos los problemas principales y cómo evitarlos.

  • Subtipos en diferentes archivos — el compilador no permitirá declarar una sealed class si los subtipos están fuera del archivo. Esta restricción garantiza un when exhaustivo.
  • Mezclar sealed y open — una sealed class no puede ser open al mismo tiempo. Si se necesita una jerarquía extensible, usa una clase abstracta normal, pero sacrificarás la exhaustividad.
  • Anidación excesiva — sealed class dentro de sealed class crea una jerarquía profunda difícil de mantener. Para escenarios simples, dos niveles son suficientes.
  • Else olvidado en when — si una sealed class de una biblioteca carece de exhaustividad, el compilador no advertirá sobre una rama faltante. Agrega else solo intencionadamente.

Preguntas frecuentes

¿Puede una sealed class tener métodos abstractos?

Sí, una sealed class puede contener métodos abstractos, y cada subtipo está obligado a implementarlos. Esto es útil cuando todas las variantes deben proporcionar una interfaz común pero con diferente lógica de ejecución.

¿Están disponibles las sealed classes en Java?

En Java 17+ se introdujeron las clases e interfaces selladas con el modificador sealed. Android actualmente admite Java 17 parcialmente, pero en proyectos Kotlin, sealed class está disponible desde Kotlin 1.0 sin restricciones.

¿Puede una sealed class heredar de otra sealed class?

Sí, una sealed class puede ser subtipo de otra. La jerarquía de sealed classes sigue siendo finita: el compilador conoce todos los subtipos en cada nivel. Esto permite construir clasificaciones detalladas de errores.

¿Afecta sealed class al rendimiento?

Sealed class no genera sobrecarga en tiempo de ejecución. El compilador optimiza las expresiones when con sealed classes en tablas de salto (tableswitch), que son más rápidas que las cadenas if-else. El rendimiento es idéntico al de enum.

¿Cómo probar jerarquías de sealed class?

Cada subtipo de sealed class se prueba por separado. Dado que sealed class es finito, se puede escribir una prueba parametrizada que itere sobre todas las variantes. Esto proporciona una cobertura completa de las ramas del bloque when.

Resumen

  • Sealed class — clase con un conjunto fijo de subtipos declarados en un mismo archivo, lo que permite un análisis exhaustivo de when en tiempo de compilación.
  • Cada subtipo de sealed class puede tener su propia estructura de datos — esta es la principal diferencia de enum, donde todas las variantes son constantes del mismo tipo.
  • Sealed interface (Kotlin 1.5+) admite herencia múltiple, sealed class solo admite herencia simple. La elección depende de la necesidad de estado compartido.
  • Sealed class es el mecanismo estándar para jerarquías de errores con seguridad de tipos en Kotlin: cada tipo de fallo es un subtipo separado con campos relevantes.
  • Patrones principales en Android: UI State, Navigation Event y Action/Intent — se construyen sobre sealed class para garantizar la integridad del manejo.
  • Evita subtipos en diferentes archivos, anidación excesiva y mezclar sealed con open — esto viola el contrato de jerarquía finita.

Desarrollaremos una aplicación móvil llave en mano

IT Sectr crea aplicaciones para iOS y Android para startups y empresas desde 2017. Le asesoraremos y le propondremos la mejor solución.

Discutir el proyecto

Lea también