Contenido del curso

Scope functions let, apply y run en Kotlin

Resumen

Las scope functions en Kotlin te permiten acceder al contexto de un objeto de forma temporal para transformar valores, modificar propiedades o devolver resultados sin escribir código repetitivo. Si trabajas con clases propias o con librerías de Java y Kotlin, dominar let, apply y run te ahorra líneas y previene errores de nulabilidad.

¿Qué son las scope functions y por qué importan?

Una scope function es una función que crea un bloque temporal donde tienes acceso directo a la instancia de un objeto. Dentro de ese bloque puedes leer sus propiedades, modificarlas o transformarlo en otro tipo. Son transversales: funcionan con cualquier clase, sea tuya o de una librería externa.

Para los ejemplos vas a trabajar con una clase Email que tiene id, subject, body e isRead con valor por defecto en false. También usarás la clase UUID de Java para generar identificadores aleatorios con UUID.randomUUID().toString() [01:30].

¿Para qué sirven las scope functions? Te dan acceso temporal al contexto de un objeto para transformarlo, modificarlo o validar su nulabilidad sin código intermedio.

¿Cómo funciona let para nulabilidad y transformaciones?

La función let cumple dos roles principales: verificar nulabilidad antes de operar sobre un valor y transformar un tipo de objeto en otro. La última expresión dentro del bloque se retorna como valor final.

Imagina que tienes un emailId que es un String? (nulable) porque viene de una búsqueda en base de datos. Con la llamada segura emailId?.let { id -> Email(id = id, subject = "Reunión", body = "Mensaje") } el bloque solo se ejecuta si emailId no es nulo, y el resultado es un objeto Email [02:50].

Dentro del bloque puedes referenciar el parámetro como it o renombrarlo, por ejemplo a id, para mayor claridad. Kotlin marca de forma estricta la diferencia entre un String nulable y uno que no lo es: si intentas asignar un valor nulable a un parámetro no nulable, el compilador te detiene.

¿Cuál es la diferencia entre it y this en scope functions? it se usa cuando la instancia llega como parámetro al bloque, como en let. this se usa cuando el objeto es el receptor implícito, como en apply y run.

¿Cuándo usar apply para configurar objetos?

La scope function apply toma la instancia del objeto y te permite modificar sus propiedades dentro del bloque, devolviendo el mismo objeto ya configurado. Es el equivalente en Kotlin al patrón de diseño builder, que en otros lenguajes requiere encadenar métodos manualmente.

En el ejemplo, un email2 se inicializa con subject = "Reunión", pero inmediatamente después se aplica:

kotlin .apply { subject = "Fiesta fin de año" }

Al imprimir email2, el subject ya no es "Reunión" sino "Fiesta fin de año" [06:10]. La modificación ocurre justo después de la declaración, antes de que la variable quede disponible para el resto del programa. Si quitas el apply, el valor original "Reunión" se conserva.

Este comportamiento es útil cuando quieres construir un objeto y dejarlo listo en una sola expresión, sin variables intermedias.

¿Qué hace run distinto a apply?

La función run también te da acceso a las propiedades del objeto mediante this, pero con una diferencia clave: devuelve el valor de la última expresión del bloque, no el objeto en sí. Eso significa que puedes transformar el resultado en cualquier tipo.

En el ejemplo se crea un email3 con subject = "Oferta de trabajo" y se le aplica run para marcar isRead = true y devolver una cadena formateada:

kotlin val email3 = Email(...).run { isRead = true "Email procesado: ${subject.uppercase()}" }

Ahora email3 no es un Email, es un String [08:40]. Si necesitas conservar el objeto y además derivar un valor, primero asigna el Email a una variable y después llama email3.run { ... } por separado.

¿Por qué run usa this y let usa it?

En run y apply, el objeto es el receptor implícito, así que accedes a sus miembros como si estuvieras dentro de la clase, usando this (que normalmente puedes omitir). En let, el objeto llega como argumento de la lambda, por eso lo referencias con it o con un nombre que tú elijas.

Ambas formas tienen el mismo efecto sobre el objeto, pero la elección depende de si lo necesitas como parámetro de otra operación o como receptor para configurarlo directamente.

Comparativa rápida entre let, apply y run

Para que tengas presente cuándo elegir cada una:

  • let: validar nulabilidad y transformar tipos. Devuelve la última expresión. Acceso con it.
  • apply: configurar propiedades de un objeto. Devuelve el mismo objeto. Acceso con this.
  • run: ejecutar lógica sobre un objeto y devolver un resultado distinto. Acceso con this.

Cada una resuelve un escenario concreto y, cuando las combinas bien, tu código queda más expresivo y seguro frente a nulos. ¿Has usado alguna de estas funciones en un proyecto real? Cuéntame en los comentarios cuál te ha resultado más útil.