Skip to content

corbat-tech/corbat-kotlin

Repository files navigation

Kotlin para desarrolladores Java — Guía completa

Preparado por @victormartingil


🧱 Fundamentos

Variables

val nombre = "Martín" // inmutable
var edad = 37         // mutable

Tipos primitivos

  • Int, Long, Double, Boolean, String, etc.
  • No hay distinción entre primitivos y wrappers como en Java.

Funciones

Forma completa:

fun saludar(nombre: String): String {
    return "Hola, $nombre"
}

Forma abreviada:

fun saludar(nombre: String): String = "Hola, $nombre"

String templates

val saludo = "Hola, $nombre"

🛠️ Clases y objetos en Kotlin

Tipos principales de clases:

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

Ejemplos:

Clase normal

class Persona(val nombre: String, var edad: Int)

Data class

data class Usuario(val id: Int, val nombre: String)

Singleton

object Configuracion {
    val version = "1.0"
}

Companion Object

class Util {
    companion object {
        fun saluda() = "Hola"
    }
}

Sealed Class

sealed class Resultado

data class Exito(val datos: String): Resultado()
data class Error(val mensaje: String): Resultado()
object Vacio : Resultado()

🔁 Control de flujo

Condicional if

Forma completa:

val resultado = if (edad >= 18) {
    "Adulto"
} else {
    "Menor"
}

Forma abreviada:

val resultado = if (edad >= 18) "Adulto" else "Menor"

when (switch mejorado)

val mensaje = when (nota) {
    10 -> "Excelente"
    in 7..9 -> "Bien"
    else -> "Insuficiente"
}

Bucles

for (i in 1..5) { println(i) }
for (item in lista) { println(item) }

🔐 Null Safety

var nombre: String? = null
val longitud = nombre?.length ?: 0
  • ?. → safe call
  • ?: → elvis operator (valor por defecto)
  • !! → assert non-null (puede lanzar NPE)

🧠 Lambdas y funciones de orden superior

val doble = { x: Int -> x * 2 }
val suma = { a: Int, b: Int -> a + b }

lista.filter { it > 0 }
lista.map { it * it }

Función que recibe lambda

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 }

📦 Funciones de ámbito (scope functions)

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")
}

🔄 Colecciones y operaciones funcionales

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 }

🧬 Destructuring

data class Persona(val nombre: String, val edad: Int)
val (nombre, edad) = Persona("Luis", 30)

🔒 Operator invoke()

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.


📚 Extension functions

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")).


🧵 Coroutines (concurrency ligera)

suspend fun obtenerDatos(): String {
    delay(1000)
    return "Listo"
}

runBlocking {
    val resultado = obtenerDatos()
    println(resultado)
}
  • suspend indica que una función puede suspenderse (como await en JS).
  • runBlocking es solo para pruebas o entry points.

🛠 Kotlin + Spring Boot

  • 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?
}

🧪 Testing moderno con Kotlin

@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() }

✅ En resumen

  • 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, object
    • invoke(), extension functions, lambdas
    • Colecciones funcionales, coroutines, when

🧠 Piensa como Java, escribe como Kotlin.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages