Kotlin Academy · Lección

lateinit e inicialización diferida

Use lateinit para propiedades asignadas posteriormente y by lazy para cálculos diferidos.

Lección 4 de 413 pasos

lateinit e inicialización diferida es una lección gratuita de Kotlin Academy en CoddyKit. Esta es la lección 4 de 4. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Kotlin Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Kotlin Academy incluye 4 lecciones en total.

Dos herramientas para la configuración diferida

A veces no puede inicializar una propiedad en el momento de construir el objeto. Kotlin proporciona lateinit (para var, asignada más adelante) y by lazy (para val, calculada en el primer acceso).

Conceptos básicos de lateinit

lateinit var pospone la inicialización. La variable debe ser una var no nula y no primitiva. Acceder a ella antes de asignarle un valor lanza UninitializedPropertyAccessException.

class Service {
    lateinit var name: String
    fun init(value: String) { name = value }
}
fun main() {
    val s = Service()
    s.init("MyService")
    println(s.name)
}

¿Por qué utilizar lateinit?

Utilice lateinit para la inyección de dependencias, los accesorios de prueba o los ciclos de vida administrados por frameworks (vistas de Android y beans de Spring), cuando la inicialización se realiza fuera del constructor.

class Repository {
    lateinit var db: String   // assigned later by DI framework
    fun query() = "querying $db"
}
fun main() {
    val r = Repository()
    r.db = "postgres://localhost"
    println(r.query())
}

Comprobación de isInitialized

Puede comprobar si se ha asignado un valor a una propiedad lateinit mediante ::propName.isInitialized.

class Foo {
    lateinit var bar: String
    fun status() = if (::bar.isInitialized) "set to $bar" else "unset"
}
fun main() {
    val f = Foo()
    println(f.status()) // unset
    f.bar = "hi"
    println(f.status())
}

Restricciones de lateinit

No puede utilizar lateinit con tipos primitivos (Int, Boolean, etc.), tipos anulables ni val. El compilador hace cumplir estas reglas.

// VALID:
lateinit var name: String
// INVALID:
// lateinit var count: Int       // primitives not allowed
// lateinit val constant: String // val not allowed
// lateinit var maybe: String?   // nullable not allowed
fun main() { name = "ok"; println(name) }

Conceptos básicos de by lazy

by lazy pospone la inicialización de un val hasta el primer acceso. La lambda se ejecuta una vez y el resultado se almacena en caché.

val expensive: String by lazy {
    println("Computing...")
    "result"
}
fun main() {
    println(expensive) // Computing... then result
    println(expensive) // result (cached)
}

¿Por qué utilizar by lazy?

Utilice by lazy cuando la inicialización sea costosa y quizá no sea necesaria (almacene el resultado en caché para usarlo más adelante), o cuando la inicialización dependa de otras propiedades ya construidas.

class Config {
    val parsed: Map<String, String> by lazy {
        println("parsing config...")
        mapOf("host" to "localhost", "port" to "8080")
    }
}
fun main() {
    val c = Config()
    println("config object created — not parsed yet")
    println(c.parsed["host"]) // now parses
    println(c.parsed["port"]) // cached
}

Modos de seguridad de subprocesos de lazy

De forma predeterminada, by lazy utiliza LazyThreadSafetyMode.SYNCHRONIZED. Utilice PUBLICATION para una inicialización apta para la concurrencia y NONE para obtener rendimiento en aplicaciones de un solo subproceso.

val safe: String by lazy { "thread-safe" }
val fast: String by lazy(LazyThreadSafetyMode.NONE) { "fast, single-thread" }
fun main() {
    println(safe)
    println(fast)
}

lateinit frente a lazy

lateinit: var asignada externamente. by lazy: val calculado por la propia propiedad en el primer acceso.

class Demo {
    lateinit var injected: String         // assigned by caller
    val computed: String by lazy { "computed once" }
}
fun main() {
    val d = Demo()
    d.injected = "from outside"
    println(d.injected)
    println(d.computed)
}

Lectura de otras propiedades con lazy

Una propiedad lazy puede leer otras propiedades (inicializadas anteriormente) y combinarlas.

class User(val first: String, val last: String) {
    val fullName: String by lazy { "$first $last" }
}
fun main() {
    val u = User("Ada", "Lovelace")
    println(u.fullName)
}

Patrón práctico

Combine lateinit para la inyección de dependencias y by lazy para el estado derivado dentro de la misma clase.

class App {
    lateinit var config: Map<String, String>
    val host: String by lazy { config["host"] ?: "localhost" }
}
fun main() {
    val app = App()
    app.config = mapOf("host" to "api.example.com")
    println(app.host) // api.example.com
}

Comprobación rápida

¿Qué palabra clave pospone la inicialización de una propiedad val hasta el primer acceso?

Resumen

Utilice lateinit var para propiedades mutables no nulas asignadas más adelante por frameworks o mediante inyección de dependencias. Utilice val by lazy para valores de solo lectura que deban calcularse una vez en el primer acceso. Compruebe el estado con ::prop.isInitialized.

Gratis para empezar

Aprende Kotlin con un tutor de IA — gratis

Escribe y ejecuta código real en tu navegador, obtén ayuda instantánea de un tutor de IA disponible 24/7 y continúa donde lo dejaste en la web o en la aplicación.

Cursos
51
Lecciones
203

Preguntas frecuentes

¿La lección «lateinit e inicialización diferida» es gratis?

Sí — el texto completo de «lateinit e inicialización diferida» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Kotlin Academy, actualiza a CoddyKit PRO. El curso de Kotlin Academy incluye 4 lecciones en total.

¿Qué aprenderé en «lateinit e inicialización diferida»?

Use lateinit para propiedades asignadas posteriormente y by lazy para cálculos diferidos. Practicas Kotlin Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.

¿Necesito experiencia previa para empezar Kotlin Academy?

No se requiere experiencia previa. Kotlin Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 4 de 4.

¿Cuánto tiempo toma la lección «lateinit e inicialización diferida»?

La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.

¿Puedo escribir y ejecutar código en esta lección de Kotlin Academy?

Sí. Cada lección de Kotlin Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.

Todas las lecciones de este curso

  1. Constructor primario y parámetros de propiedades
  2. Bloques init y orden de inicialización
  3. Getters y setters personalizados con field
  4. lateinit e inicialización diferida
← Volver a Kotlin Academy