Especificidades de Kotlin en desarrollo móvil: qué es, qué construcciones y cómo funciona

Autor: IT Sectr Publicado: 2026-06-29 Tiempo de lectura: 11 min

Kotlin es el lenguaje principal para el desarrollo de Android. Según Google Android Docs (2025), más del 95% de los nuevos proyectos en Android usan Kotlin. Comprender las especificidades de Kotlin — data class, sealed class, corrutinas y scope functions — es un requisito obligatorio para un desarrollador Android.

Puntos Clave

  • data class — generación automática de equals/hashCode/toString/copy/componentN. Para modelos de datos. sealed class — jerarquía de tipos restringida con verificación when.
  • Scope functions: let, run, with, apply, also. Se diferencian por contexto (it vs this) y valor de retorno.
  • Corrutinas: launch (fire-and-forget), async (con resultado), runBlocking (puente), withContext (cambio de Dispatcher).
  • lifecycleScope y viewModelScope — corrutinas Lifecycle-aware sin cancelación manual.
  • reified — preservación del tipo en funciones inline. lateinit/lazy — inicialización diferida.

Clases (data class, sealed class, object, companion object)

Kotlin extiende los conceptos de clases de Java. data class, sealed class, object y companion object — construcciones que no existen en Java o se implementan de manera diferente.

data class vs sealed class

data class — una clase que genera automáticamente equals(), hashCode(), toString(), copy() y componentN(). Ideal para modelos de datos (DTO, Entity). Requisitos: al menos un parámetro en el constructor primario, val/var, no puede ser open/sealed/inner. sealed class — una clase con una jerarquía de subclases restringida. Todas las subclases se conocen en tiempo de compilación y se declaran en el mismo archivo. La expresión when con sealed class no requiere una rama else. sealed interface (Kotlin 1.9+) — igual que sealed class pero permite herencia múltiple. object — un singleton, declarado con la palabra clave object (no class). Inicialización perezosa thread-safe. companion object — miembros estáticos de una clase. Tiene un nombre (Companion por defecto). Puede implementar interfaces y tener extension functions.

Tipo Descripción Uso
data classGeneración automática de equals, hashCode, toString, copyModelos de datos, DTO, Entity
sealed classJerarquía restringida, verificación whenEstados, Resultado, UI State
sealed interfacesealed class + herencia múltipleEventos, Acciones (Kotlin 1.9+)
objectSingleton (declarativo)Factory, Utility, Constantes
companion objectMiembros estáticos de claseFactory Method, constantes estáticas
enum classEnumeración con constantesEstados con conjunto fijo

data class — para el 90% de los modelos. sealed class — para UI State y Resultado. object — para singletons. IT Sectr recomienda sealed class para todos los estados de pantalla (Loading, Success, Error).

Sealed class en la práctica

Sealed class — una herramienta poderosa para modelar estados. Ejemplo: UiState<T> con subclases Loading, Success(data: T), Error(message: String). La expresión when garantiza el manejo de todos los estados. Sealed interface — para eventos y acciones donde se necesita implementación múltiple. Value class (Kotlin 1.5+) — un envoltorio para un solo valor sin overhead. Se usa para identificadores type-safe: @JvmInline value class UserId(val id: String).

Funciones (extension, inline, higher-order, scope functions)

Extension Function — agregar un método a una clase existente sin herencia. fun String.isEmail(): Boolean. Extension Property — igual para propiedades (sin backing field). Inline Function — inserción del cuerpo de la función en el lugar de llamada — sin overhead de llamada. Se usa para higher-order functions con lambdas. Higher-Order Function — una función que toma o devuelve otra función. Scope Functions — cinco funciones para trabajar con el contexto de un objeto: let, run, with, apply, also.

Scope Functions

let — contexto it, devuelve resultado de lambda. Se usa para llamadas null-safe (?.let {}). apply — contexto this, devuelve contexto. Para configuración de objetos. run — contexto this, devuelve resultado de lambda. Para cálculos con contexto. also — contexto it, devuelve contexto. Para efectos secundarios (logging). with — no es extension, contexto this, devuelve resultado de lambda. Para un grupo de operaciones sobre un objeto. Lambda — función anónima. Destructuring Declaration — desempaquetado de data class en variables: val (name, age) = person.

Inline + reified

Inline function con reified — la única forma de preservar un tipo genérico en JVM. Se usa para: builders type-safe (Gson.fromJson<T>()), verificación de tipos (is T), obtención de la clase (T::class). Crossinline y Noinline — modificadores para parámetros lambda en funciones inline. crossinline — prohíbe el non-local return, noinline — prohíbe la inserción de una lambda específica. IT Sectr recomienda inline + reified solo cuando se trabaja con tipos; para funciones higher-order regulares, inline puede aumentar el tamaño del bytecode.

Corrutinas (Coroutine Builder, Dispatchers, Scope)

Corrutinas — hilos ligeros para programación asíncrona. No bloquean el hilo — se suspenden. suspend function — una función que puede suspenderse sin bloquear el hilo. Solo puede llamarse desde una corrutina u otra suspend function.

CoroutineScope

CoroutineScope — un ámbito para corrutinas. Contiene CoroutineContext (Job + Dispatcher). lifecycleScope — para Activity/Fragment (Lifecycle-aware). viewModelScope — para ViewModel (cancelación automática en onCleared()). GlobalScope — ámbito global (no recomendado en producción — fugas de memoria). Dispatchers: Dispatchers.Main (UI), Dispatchers.IO (red/disco), Dispatchers.Default (CPU-intensive), Dispatchers.Unconfined (no recomendado). launch — inicia una corrutina: Job. async — inicia con resultado: Deferred<T>. runBlocking — puente bloqueante. withContext — cambia Dispatcher dentro de una suspend function.

kotlin
// Ejemplo de corrutinas: carga de datos en ViewModel
class MainViewModel : ViewModel() {
    private val _state = MutableStateFlow<UiState>(UiState.Loading)
    val state: StateFlow<UiState> = _state.asStateFlow()

    fun loadData() {
        viewModelScope.launch {
            _state.value = UiState.Loading
            try {
                val data = withContext(Dispatchers.IO) {
                    repository.fetchData()
                }
                _state.value = UiState.Success(data)
            } catch (e: Exception) {
                _state.value = UiState.Error(e.message)
            }
        }
    }
}

// Solicitudes paralelas con async
suspend fun loadCombinedData(): CombinedData = coroutineScope {
    val users = async(Dispatchers.IO) { api.getUsers() }
    val posts = async(Dispatchers.IO) { api.getPosts() }
    CombinedData(users.await(), posts.await())
}

viewModelScope.launch — inicio estándar de corrutina en ViewModel. withContext(Dispatchers.IO) — cambio al hilo IO para solicitud de red. Dispatchers determinan en qué grupo de hilos se ejecuta la corrutina. IT Sectr recomienda viewModelScope para ViewModel y lifecycleScope para Activity/Fragment.

Características avanzadas (reified, destructuring, lateinit/lazy)

reified — un modificador de tipo en funciones inline. Permite usar el tipo: T::class, is T, as T. Sin reified, los genéricos en JVM se borran (type erasure). inline fun + reified — una combinación poderosa para APIs type-safe. Destructuring Declaration — val (x, y) = point. Funciona para data class y tipos con componentN(). typealias — alias de tipo: typealias Callback = (String) -> Unit. lateinit — inicialización diferida de var (para dependency injection). No thread-safe. lazy — inicialización perezosa de val (thread-safe por defecto). lazy(LazyThreadSafetyMode.NONE) — sin sincronización. Extension function y Extension property — agregar funcionalidad sin herencia. Kotlin es un lenguaje donde las extension functions resuelven el 90% de las tareas de utilidad.

Propiedades Delegadas

Delegated Properties — delegar getter/setter a otro objeto. Delegados estándar: lazy, observable, vetoable, map. Delegado personalizado mediante operadores getValue/setValue. by — palabra clave de delegación: val name by lazy { loadName() }. Las propiedades delegadas son la base para los delegados de ViewModel (by viewModels()). IT Sectr recomienda lazy para inicialización diferida y Delegates.observable para observar cambios.

Característica Descripción Ejemplo
reifiedPreservación del tipo genérico en inlineinline fun <reified T> parse(): T
destructuringDesempaquetado de data classval (name, age) = person
typealiasAlias de tipotypealias Orders = List<Order>
lateinitInicialización diferida de varlateinit var adapter: Adapter
lazyInicialización perezosa de valval config by lazy { load() }
delegatedDelegación de propiedadesvar x by Delegates.observable(0)

reified — para APIs type-safe. lazy — para carga diferida. delegated properties — para reutilizar la lógica de propiedades. IT Sectr recomienda dominar todas estas características para un desarrollo efectivo en Kotlin.

Flow y StateFlow

Flow — flujo de datos asíncrono frío en Kotlin. Emite valores bajo demanda del colector. StateFlow — Flow caliente con un único valor actual. Se usa en ViewModel para UI State. SharedFlow — Flow caliente para eventos (eventos únicos). flowOf, asFlow — creación de Flow desde colecciones. catch, retry, debounce — operadores. stateIn, shareIn — conversión de Flow frío a caliente. IT Sectr recomienda StateFlow para UI State y SharedFlow para eventos (Snackbar, navegación).

kotlin
class SearchViewModel : ViewModel() {
    private val _query = MutableStateFlow("")
    val suggestions: StateFlow<List<String>> = _query
        .debounce(300)
        .filter { it.length >= 2 }
        .flatMapLatest { repository.search(it) }
        .stateIn(viewModelScope, SharingStarted.WhileSubscribed(5000), emptyList())

    fun onQueryChanged(query: String) {
        _query.value = query
    }
}

Serialización (kotlinx.serialization, Parcelize)

kotlinx.serialization — biblioteca de Kotlin para serialización JSON. @Serializable — anotación. @SerialName — nombre de campo personalizado. Soporta: JSON, CBOR, ProtoBuf. Parcelize — @Parcelize para Android Parcelable (sin implementación manual). Gson vs Moshi vs kotlinx: kotlinx.serialization — Kotlin-first, compile-safe, sin reflection. Moshi — anotaciones + codegen. IT Sectr recomienda kotlinx.serialization para nuevos proyectos y Moshi para los existentes.

kotlin
@Serializable
data class ApiResponse<T>(
    val success: Boolean,
    @SerialName("data") val data: T? = null,
    val error: String? = null
)

@Serializable
data class User(
    val id: Int,
    val name: String,
    val email: String
)

// Deserialización
val json = Json { ignoreUnknownKeys = true }
val response = json.decodeFromString<ApiResponse<List<User>>>(jsonString)
println("Users: ${response.data?.size ?: 0}")

Preguntas Frecuentes

¿Cuál es la diferencia entre data class y sealed class?

data class — para datos (generación automática de equals/hashCode/copy). sealed class — para jerarquía de tipos (verificación en when). sealed interface — igual con herencia múltiple.

¿Qué son las scope functions en Kotlin?

let, run, with, apply, also. Se diferencian por contexto (it vs this) y valor de retorno (result vs context). let — null safety, apply — configuración, also — efectos secundarios.

¿Qué es CoroutineScope y qué tipos existen?

CoroutineScope — un ámbito para corrutinas. lifecycleScope — para Activity, viewModelScope — para ViewModel. GlobalScope — no recomendado.

¿Qué es reified en Kotlin?

reified — preservación del tipo en funciones inline. Permite T::class e is T. Solo funciona con funciones inline.

¿Qué son los coroutine builders: launch, async, runBlocking?

launch — sin resultado. async — con resultado (Deferred). runBlocking — puente bloqueante para main/test. withContext — cambio de Dispatcher.

Resumen

  • data class — para modelos. sealed class — para estados. object — para singletons.
  • Scope functions: let (null-safe), apply (configuración), run (cálculos), also (logging).
  • Corrutinas: launch (fire-and-forget), async (con resultado), withContext (cambio de Dispatcher).
  • viewModelScope — estándar para ViewModel. lifecycleScope — para Activity/Fragment.
  • reified — funciones inline type-safe. lateinit — DI, lazy — inicialización perezosa.
  • Extension functions — agregue funcionalidad sin herencia.
  • Dispatchers: Main (UI), IO (red/disco), Default (CPU). Elija el correcto.

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