Preparado por @victormartingil
val nombre = "Martín" // inmutable
var edad = 37 // mutableInt,Long,Double,Boolean,String, etc.- No hay distinción entre primitivos y wrappers como en Java.
Forma completa:
fun saludar(nombre: String): String {
return "Hola, $nombre"
}Forma abreviada:
fun saludar(nombre: String): String = "Hola, $nombre"val saludo = "Hola, $nombre"| Tipo | Descripción | Ejemplo | Equivalente en Java |
|---|---|---|---|
class |
Clase normal | class Persona(val nombre: String) |
Clase común |
data class |
Clase para representar datos (inmutable por defecto) | data class Usuario(val id: Int) |
record desde Java 16 |
object |
Singleton | object Logger { fun log() } |
Singleton con instancia estática |
companion object |
Miembro estático en clase | companion object { fun create() } |
static en Java |
sealed class |
Jerarquía de clases cerrada | sealed class Resultado |
sealed class desde Java 15 |
enum class |
Enumeración | enum class Color { RED, GREEN } |
enum |
interface |
Contrato sin implementación | interface Animal |
interface |
class Persona(val nombre: String, var edad: Int)data class Usuario(val id: Int, val nombre: String)object Configuracion {
val version = "1.0"
}class Util {
companion object {
fun saluda() = "Hola"
}
}sealed class Resultado
data class Exito(val datos: String): Resultado()
data class Error(val mensaje: String): Resultado()
object Vacio : Resultado()Forma completa:
val resultado = if (edad >= 18) {
"Adulto"
} else {
"Menor"
}Forma abreviada:
val resultado = if (edad >= 18) "Adulto" else "Menor"val mensaje = when (nota) {
10 -> "Excelente"
in 7..9 -> "Bien"
else -> "Insuficiente"
}for (i in 1..5) { println(i) }
for (item in lista) { println(item) }var nombre: String? = null
val longitud = nombre?.length ?: 0?.→ safe call?:→ elvis operator (valor por defecto)!!→ assert non-null (puede lanzar NPE)
val doble = { x: Int -> x * 2 }
val suma = { a: Int, b: Int -> a + b }
lista.filter { it > 0 }
lista.map { it * it }Forma completa:
fun operar(a: Int, b: Int, f: (Int, Int) -> Int): Int {
return f(a, b)
}Forma abreviada:
fun operar(a: Int, b: Int, f: (Int, Int) -> Int): Int = f(a, b)Uso:
val resultado = operar(2, 3) { x, y -> x * y }| Función | Contexto | Devuelve | Uso principal |
|---|---|---|---|
let |
it |
Resultado lambda | Transformaciones seguras |
run |
this |
Resultado lambda | Inicializaciones |
with |
this |
Resultado lambda | Operaciones agrupadas |
apply |
this |
Objeto receptor | Configuración de objetos |
also |
it |
Objeto receptor | Efectos secundarios (logging) |
Ejemplo:
val usuario = Usuario(1, "Martín").apply {
println("Creado: $this")
}val numeros = listOf(1, 2, 3, 4)
val pares = numeros.filter { it % 2 == 0 }
val cuadrados = numeros.map { it * it }
val suma = numeros.reduce { acc, n -> acc + n }
val producto = numeros.fold(1) { acc, n -> acc * n }data class Persona(val nombre: String, val edad: Int)
val (nombre, edad) = Persona("Luis", 30)Permite que una clase se comporte como una función:
class MiServicio {
operator fun invoke(): String {
return "Ejecutado"
}
}Forma abreviada:
class MiServicio {
operator fun invoke(): String = "Ejecutado"
}Uso:
val servicio = MiServicio()
println(servicio()) // Llama a invoke()Muy útil en servicios y use cases. En Java se haría con servicio.invoke() manualmente.
Permiten agregar métodos a clases existentes sin herencia:
fun String.gritar(): String {
return this.uppercase() + "!!!"
}Forma abreviada:
fun String.gritar() = this.uppercase() + "!!!"Uso:
val mensaje = "hola".gritar() // "HOLA!!!"En Java esto se haría con una clase utilitaria estática (StringUtils.gritar("hola")).
suspend fun obtenerDatos(): String {
delay(1000)
return "Listo"
}
runBlocking {
val resultado = obtenerDatos()
println(resultado)
}suspendindica que una función puede suspenderse (comoawaiten JS).runBlockinges solo para pruebas o entry points.
- Compatible con
@RestController,@Service,@Repository... - Usa inyección por constructor directamente (gracias al constructor primario de Kotlin):
@Service
class MiServicio(val repositorio: ClienteRepository)- Puedes usar interfaces declarativas:
interface UserRepository : JpaRepository<User, Long> {
fun findByEmail(email: String): User?
}@Test
fun `debería retornar true si es par`() {
val esPar = { x: Int -> x % 2 == 0 }
assertTrue(esPar(4))
}Y con MockK:
every { servicio.obtener() } returns Resultado.Exito("ok")
verify { servicio.obtener() }-
Kotlin es conciso, expresivo y seguro frente a
null. -
Te permite escribir menos código y más claro.
-
Todo es interoperable con Java, puedes usar ambas en el mismo proyecto.
-
Sus características clave para backend son:
data class,sealed class,objectinvoke(),extension functions,lambdas- Colecciones funcionales, coroutines,
when
🧠 Piensa como Java, escribe como Kotlin.