Curso de Kotlin

Sealed interfaces para modelar acciones en Kotlin

Curso de Kotlin

Contenido del curso

Sealed interfaces para modelar acciones en Kotlin

Resumen

Las sealed interfaces en Kotlin te permiten modelar un conjunto limitado de acciones que comparten un contrato común, ideal para representar comandos de usuario o eventos que disparan procesos. A diferencia de las sealed classes, brillan cuando necesitas describir acciones que recaen sobre una pantalla o sistema, no estados.

¿Qué es una sealed interface y cuándo la uso?

Una sealed interface funciona como un contrato cerrado: solo un grupo definido de clases puede implementarla. Esto te da control total sobre las variantes posibles dentro de un sistema.

¿Cuál es la diferencia entre sealed class y sealed interface? La sealed class se usa mejor para representar estados de UI (loading, success, error). La sealed interface funciona mejor para describir acciones o comandos que aplican a una interfaz [01:00].

La ventaja real aparece cuando esas acciones comparten parámetros. Como toda interfaz, define un contrato, y cada implementación debe cumplirlo.

¿Cómo declaro una sealed interface con un contrato compartido?

En el ejemplo de la clase modelamos un sistema de correo con la interfaz EmailAction, que obliga a cada acción a implementar la propiedad actionType: String [02:30].

kotlin sealed interface EmailAction { val actionType: String }

data class Send(val recipient: String, val subject: String) : EmailAction { override val actionType: String = "send" }

data class Delete(val emailId: String) : EmailAction { override val actionType: String = "delete" }

data object SaveDraft : EmailAction { override val actionType: String = "draft" }

data object Refresh : EmailAction { override val actionType: String = "refresh" }

Fíjate en algo clave: usamos data class cuando la acción lleva parámetros (como recipient o emailId) y data object cuando la acción no necesita datos extra, como Refresh o SaveDraft.

¿Cómo mapeo entradas de usuario a acciones tipadas?

Un patrón muy común consiste en leer un comando por consola y transformarlo en una acción concreta. Aquí entra when como herramienta central de transformación.

kotlin val action: EmailAction = when (comando) { 1 -> EmailAction.Send(email.remitente, email.subject) 2 -> EmailAction.Delete(email.id) 3 -> EmailAction.Refresh 4 -> EmailAction.SaveDraft else -> throw RuntimeException("Comando no existe") }

Una de las aplicaciones más potentes de when con sealed interfaces es justamente esa: transformar un tipo de dato en otro de forma segura y exhaustiva [07:45].

¿Cómo convierto una acción en un estado de UI?

Este patrón se ve muchísimo en desarrollo Android: una acción del usuario se reduce a un estado de UI. Para eso definimos una sealed class UIState con tres variantes: Success, Loading y Error.

kotlin fun processActionToState(action: EmailAction): UIState { println("Ejecutando comando: ${action.actionType}") return when (action) { is EmailAction.Delete -> UIState.Error is EmailAction.Refresh -> UIState.Success is EmailAction.SaveDraft -> UIState.Success is EmailAction.Send -> UIState.Success } }

Imagina el escenario real: intentas borrar un correo, pero el backend falla o el teléfono pierde Internet. Ese flujo se traduce naturalmente en UIState.Error. Para Refresh, primero podrías emitir Loading y luego Success cuando termine la operación.

¿Por qué imprimir el actionType fuera del when?

El reto de la clase pedía añadir un println que mostrara qué acción se está ejecutando usando la propiedad compartida actionType. La tentación es repetir el print dentro de cada rama del when, pero hay una forma mejor.

¿Dónde coloco código que aplica a todas las ramas de un when? Si es una propiedad compartida del contrato, ponla fuera del when para que se ejecute solo una vez. Reduces líneas de código y eres más amable con la memoria [11:30].

Esta es una buena práctica de eficiencia: identificar qué pertenece al contrato común y extraerlo del bloque condicional.

¿Cuándo elegir sealed interface vs sealed class?

La recomendación práctica del instructor resume bien la decisión:

  • Usa sealed interfaces para modelar acciones del usuario que desencadenan procesos.
  • Usa sealed classes para representar estados de UI que resultan de esas operaciones.
  • Combina ambas con when para mapear acciones a estados de forma segura y exhaustiva.

Este patrón también funciona muy bien en backends para ejecutar cadenas de acciones encadenadas con resultados predecibles.

¿En qué proyecto vas a aplicar primero las sealed interfaces? Cuéntame en los comentarios cómo modelarías tus acciones.