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
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 — 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 class | Generación automática de equals, hashCode, toString, copy | Modelos de datos, DTO, Entity |
| sealed class | Jerarquía restringida, verificación when | Estados, Resultado, UI State |
| sealed interface | sealed class + herencia múltiple | Eventos, Acciones (Kotlin 1.9+) |
| object | Singleton (declarativo) | Factory, Utility, Constantes |
| companion object | Miembros estáticos de clase | Factory Method, constantes estáticas |
| enum class | Enumeración con constantes | Estados 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 — 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).
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.
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 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 — 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 — 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.
// 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.
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.
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 |
|---|---|---|
| reified | Preservación del tipo genérico en inline | inline fun <reified T> parse(): T |
| destructuring | Desempaquetado de data class | val (name, age) = person |
| typealias | Alias de tipo | typealias Orders = List<Order> |
| lateinit | Inicialización diferida de var | lateinit var adapter: Adapter |
| lazy | Inicialización perezosa de val | val config by lazy { load() } |
| delegated | Delegación de propiedades | var 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 — 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).
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
}
}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.
@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
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.
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.
CoroutineScope — un ámbito para corrutinas. lifecycleScope — para Activity, viewModelScope — para ViewModel. GlobalScope — no recomendado.
reified — preservación del tipo en funciones inline. Permite T::class e is T. Solo funciona con funciones inline.
launch — sin resultado. async — con resultado (Deferred). runBlocking — puente bloqueante para main/test. withContext — cambio de Dispatcher.
Resumen
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.