Las variables, los tipos de datos y las funciones son los bloques fundamentales con los que construyes cualquier programa en Kotlin.
Variables: val y var
Kotlin tiene dos palabras clave para declarar variables: val y var.
valdeclara una variable de solo lectura. Una vez que le asignas un valor, no puede cambiar.vardeclara una variable mutable. Su valor puede cambiar en cualquier momento.
val nombreEmpresa = "Bimbo" // no se puede reasignar
var precioProducto = 18.50 // sí se puede reasignar
precioProducto = 20.00 // válido
Usa val siempre que sea posible. Reduce errores y hace tu código más predecible.
Tipos de datos primitivos en Kotlin
Kotlin es un lenguaje con tipado estático. Cada variable tiene un tipo definido en tiempo de compilación.
Tipos numéricos
| Tipo | Descripción | Ejemplo |
|---|---|---|
Int |
Entero de 32 bits | val unidades: Int = 500 |
Long |
Entero de 64 bits | val ventas: Long = 1_000_000L |
Double |
Decimal de 64 bits | val precio: Double = 199.99 |
Float |
Decimal de 32 bits | val tasa: Float = 0.16f |
Tipo texto y lógico
| Tipo | Descripción | Ejemplo |
|---|---|---|
String |
Cadena de texto | val ciudad: String = "Monterrey" |
Boolean |
Verdadero o falso | val activo: Boolean = true |
Char |
Un solo carácter | val inicial: Char = 'F' |
Inferencia de tipos
Kotlin puede inferir el tipo automáticamente si asignas un valor en la declaración.
val sucursal = "Liverpool Perisur" // Kotlin infiere String
var stock = 340 // Kotlin infiere Int
var descuento = 0.15 // Kotlin infiere Double
No necesitas escribir el tipo si el valor inicial lo deja claro.
Plantillas de cadena (String Templates)
Kotlin permite insertar variables directamente dentro de un String usando el símbolo $.
val producto = "Gansito"
val precio = 12
println("El producto $producto cuesta $$precio") // El producto Gansito cuesta $12
Para expresiones más complejas, usa llaves: ${expresion}.
val salario = 18500
val bono = 2000
println("Total a pagar: $${salario + bono}") // Total a pagar: $20,500
Esta sintaxis es más limpia que concatenar con +.
Funciones en Kotlin
Una función es un bloque de código que realiza una tarea específica y puede reutilizarse.
Sintaxis básica
fun nombreFuncion(parametro: Tipo): TipoDeRetorno {
// cuerpo de la función
return valor
}
Ejemplo 1 — Función simple sin retorno
fun saludarCliente(nombre: String) {
println("Bienvenido a FEMSA, $nombre")
}
saludarCliente("Carlos") // Bienvenido a FEMSA, Carlos
Cuando una función no devuelve nada, su tipo de retorno es Unit. Puedes omitirlo.
Ejemplo 2 — Función con retorno
fun calcularTotal(precio: Double, cantidad: Int): Double {
return precio * cantidad
}
val total = calcularTotal(49.90, 6)
println("Total: $$total") // Total: $299.4
Ejemplo 3 — Función con valor predeterminado
Kotlin permite asignar valores por defecto a los parámetros.
fun aplicarDescuento(precio: Double, descuento: Double = 0.10): Double {
return precio - (precio * descuento)
}
println(aplicarDescuento(1200.0)) // aplica 10% por defecto
println(aplicarDescuento(1200.0, 0.20)) // aplica 20%
Esto evita crear múltiples versiones de la misma función.
Funciones de expresión única
Si el cuerpo de tu función es una sola expresión, puedes escribirla en una línea.
fun calcularIVA(precio: Double): Double = precio * 0.16
val iva = calcularIVA(500.0)
println("IVA: $$iva") // IVA: $80
Esta sintaxis es común en proyectos Android profesionales en México y en todo el mundo.
El sistema de tipos nulo-seguro (Null Safety)
Esta es una de las características más importantes de Kotlin. En Java, un valor nulo puede romper tu app sin advertencia. En Kotlin, el compilador te obliga a manejar los nulos explícitamente.
Variable nullable
Agrega ? al tipo para permitir que una variable guarde null.
var correo: String? = null
correo = "ventas@mercadolibre.com.mx"
Sin el ?, Kotlin no te permite asignar null a esa variable.
Operador de llamada segura ?.
Usa ?. para acceder a propiedades o métodos de una variable nullable sin riesgo de error.
var nombreUsuario: String? = null
println(nombreUsuario?.length) // imprime null, no lanza excepción
Operador Elvis ?:
El operador Elvis (?:) define un valor alternativo cuando la variable es null.
val nombre: String? = null
val nombreFinal = nombre ?: "Cliente anónimo"
println(nombreFinal) // Cliente anónimo
Este patrón es muy común al leer datos desde una API o una base de datos.
Operador de aserción no nula !!
Usa !! solo cuando estás completamente seguro de que el valor no es null.
val codigo: String? = "MX-4821"
println(codigo!!.length) // 7
Si el valor sí es null y usas !!, tu app lanzará una excepción en tiempo de ejecución. Úsalo con cuidado.
Ejemplo integrador — Sistema de precios para una tienda
Este ejemplo combina variables, tipos, funciones y null safety en un caso real.
fun obtenerNombreProducto(id: Int): String? {
return when (id) {
1 -> "Marinela Pingüinos"
2 -> "Bimbo Pan Blanco"
else -> null
}
}
fun mostrarPrecio(id: Int, precio: Double) {
val nombre = obtenerNombreProducto(id) ?: "Producto desconocido"
val iva = calcularIVA(precio)
val total = precio + iva
println("Producto: $nombre")
println("Precio base: $$precio")
println("IVA (16%): $$iva")
println("Total con IVA: $$total")
}
fun calcularIVA(precio: Double): Double = precio * 0.16
mostrarPrecio(2, 38.50)
Salida esperada:
Producto: Bimbo Pan Blanco
Precio base: $38.5
IVA (16%): $6.16
Total con IVA: $44.66
Errores comunes
Error 1 — Intentar reasignar un val
val empresa = "FEMSA"
empresa = "Oxxo" // ERROR: val cannot be reassigned
Solución: Cambia val por var si necesitas reasignar el valor.
Error 2 — Olvidar el tipo de retorno
fun calcularSalario(horas: Int, pago: Double) { // falta el tipo de retorno
horas * pago // esta expresión no se devuelve
}
Solución: Declara el tipo de retorno y usa return.
fun calcularSalario(horas: Int, pago: Double): Double {
return horas * pago
}
Error 3 — Acceder a una variable nullable sin protección
var telefono: String? = null
println(telefono.length) // ERROR de compilación
Solución: Usa ?. o el operador Elvis.
println(telefono?.length ?: "Sin teléfono")
Error 4 — Confundir Int con Double en operaciones
val resultado = 7 / 2
println(resultado) // imprime 3, no 3.5
Kotlin divide dos enteros y da un entero. Solución: usa literales Double.
val resultado = 7.0 / 2.0
println(resultado) // imprime 3.5
Tabla de referencia rápida
| Concepto | Sintaxis | Notas |
|---|---|---|
| Variable inmutable | val nombre = valor |
No se puede reasignar |
| Variable mutable | var nombre = valor |
Se puede reasignar |
| Función básica | fun nombre(p: Tipo): Tipo { } |
Usa return |
| Función de una línea | fun nombre(p: Tipo): Tipo = expr |
Sin llaves ni return |
| Nullable | var x: String? = null |
Permite null |
| Llamada segura | objeto?.propiedad |
Devuelve null si es nulo |
| Operador Elvis | valor ?: alternativa |
Valor si no es null |
| Valor predeterminado | fun f(p: Tipo = default) |
Parámetro opcional |