Sintaxis básica
Las funciones en Kotlin se declaran con fun. El tipo de retorno va después de los parámetros:
// fun nombre(parametros): TipoRetorno { cuerpo }
fun saludar(nombre: String): String {
return "Hola, $nombre!"
}
// Sin retorno — Unit es el equivalente de void en Java
fun imprimirMensaje(mensaje: String): Unit {
println(mensaje)
}
// Unit se puede omitir (es el default)
fun imprimirMensaje(mensaje: String) {
println(mensaje)
}
// Múltiples parámetros
fun sumar(a: Int, b: Int): Int {
return a + b
}
Parámetros con valores default
Los parámetros pueden tener valores por default, eliminando la necesidad de múltiples sobrecargas:
fun conectar(
host: String,
puerto: Int = 8080,
timeout: Long = 5000L,
ssl: Boolean = false
) {
// ...
}
// Llamadas válidas:
conectar("api.ejemplo.com") // usa todos los defaults
conectar("api.ejemplo.com", 443, ssl = true) // puerto 443, timeout default
conectar("api.ejemplo.com", timeout = 10000L) // solo sobreescribís timeout
// En Java necesitarías 4 métodos sobrecargados para esto.
// En Kotlin, una sola función lo hace todo.
Named arguments
Podés nombrar los argumentos al llamar una función. Esto mejora la legibilidad y permite pasarlos en cualquier orden:
fun crearUsuario(nombre: String, edad: Int, admin: Boolean = false): Usuario {
return Usuario(nombre, edad, admin)
}
// Sin named args — qué significa cada valor?
crearUsuario("Carlos", 30, true) // confuso
// Con named args — auto-documentado
crearUsuario(
nombre = "Carlos",
edad = 30,
admin = true
)
// Podés cambiar el orden cuando usás nombres
crearUsuario(
admin = false,
nombre = "Ana",
edad = 25
)
Cuándo usar named argsSiempre que una función tenga más de 2 parámetros del mismo tipo, o parámetros booleanos. crearUsuario("Carlos", 30, true, false, true) es ilegible. Con named args es imposible equivocarse el orden.
Single-expression functions
Cuando una función solo retorna una expresión, podés escribirla en una línea con =:
// Forma larga
fun cuadrado(n: Int): Int {
return n * n
}
// Single-expression — el tipo de retorno se infiere
fun cuadrado(n: Int) = n * n
// Funciona con cualquier expresión, incluso when
fun descripcionEdad(edad: Int) = when {
edad < 13 -> "niño"
edad < 18 -> "adolescente"
edad < 65 -> "adulto"
else -> "adulto mayor"
}
// Muy común en Android para propiedades computadas y ViewModels
fun esMayorDeEdad(usuario: Usuario) = usuario.edad >= 18
Unit y Nothing
// Unit — función que no retorna un valor útil
fun log(mensaje: String): Unit = println(mensaje)
// Nothing — función que NUNCA retorna (siempre lanza o es un loop infinito)
fun lanzarError(mensaje: String): Nothing {
throw IllegalStateException(mensaje)
}
// Nothing es útil en combinación con Elvis para fallar rápido:
val usuario = buscarUsuario(id) ?: lanzarError("Usuario $id no encontrado")
// A partir de acá, el compilador sabe que usuario no es null
Funciones locales
Podés definir funciones dentro de otras funciones para encapsular lógica auxiliar sin contaminar el scope de la clase:
fun procesarPedido(items: List- ): Resumen {
// Función local — solo visible dentro de procesarPedido
fun calcularDescuento(precio: Double, cantidad: Int): Double {
return if (cantidad > 10) precio * 0.9 else precio
}
val total = items.sumOf { item ->
calcularDescuento(item.precio, item.cantidad) * item.cantidad
}
return Resumen(total, items.size)
}
Extension functions — la feature que cambia todo
Las extension functions te permiten agregar funciones a clases existentes sin modificarlas ni heredar de ellas. Son una de las features más poderosas de Kotlin:
// Agregar una función a String sin modificar la clase String
fun String.esPalindromo(): Boolean {
return this == this.reversed()
}
// Usarla como si fuera un método nativo de String
"kayak".esPalindromo() // true
"kotlin".esPalindromo() // false
// Agregar función a Int
fun Int.esPar() = this % 2 == 0
4.esPar() // true
// Uso real en Android — extensiones sobre Context, View, etc.
fun Context.showToast(mensaje: String) {
Toast.makeText(this, mensaje, Toast.LENGTH_SHORT).show()
}
// En tu Activity o Fragment:
showToast("Guardado correctamente") // en lugar de Toast.makeText(...).show()
// Extension sobre List para operaciones de negocio
fun List.totalConDescuento(descuento: Double): Double {
return sumOf { it.precio } * (1 - descuento)
}
Las extension functions no modifican la claseSon azúcar sintáctico — el compilador las convierte en funciones estáticas que reciben el objeto como primer parámetro. No pueden acceder a miembros privados de la clase. Si el objeto es null, necesitás declararlas como fun String?.extension().