1

Entendiendo las diferencias entre apply, also, with y run en Kotlin

¿Alguna vez te has preguntado cómo simplificar el código que utiliza un objeto en varias operaciones en Kotlin? ¿Te gustaría aprender cómo mejorar la legibilidad y la concisión de tu código sin sacrificar la funcionalidad? Si es así, entonces este tutorial es para ti.

En este tutorial, exploraremos las funciones de alto nivel apply, also, with y run y aprenderemos cómo utilizarlas para simplificar y mejorar el código que utiliza un objeto en varias operaciones. Aprenderemos sus diferencias y cómo aplicarlas en diferentes situaciones para mejorar la legibilidad y la concisión de nuestro código.

Así que si estás interesado en aprender cómo mejorar tu código Kotlin mediante el uso de estas poderosas funciones, ¡sigue leyendo! Veremos ejemplos prácticos y aprenderemos a utilizar estas funciones de manera efectiva para mejorar la legibilidad y la concisión de nuestro código. Al final de este tutorial, tendrás una mejor comprensión de cómo aplicar apply, also, with y run en tu propio código Kotlin y cómo elegir la función adecuada para cada situación. ¡Así que empecemos!

Introducción a las funciones de extensión en Kotlin
Las funciones de extensión en Kotlin nos permiten agregar nuevas funcionalidades a clases existentes sin tener que heredar de ellas o utilizar patrones de diseño como el wrapper. Esto nos permite mejorar la legibilidad y la concisión de nuestro código sin sacrificar la funcionalidad.

Para utilizar una función de extensión, simplemente debemos definirla como una función normal y utilizar la palabra clave fun seguida del tipo receptor (el objeto al que queremos agregar la nueva funcionalidad) y el nombre de la función. Luego, podemos utilizar la función de extensión como si fuera una función normal del objeto receptor.
Por ejemplo, podríamos crear una función de extensión para la clase String que convierta una cadena en mayúsculas:

funString.toUppercase(): String {
    returnthis.toUpperCase()
}

Luego, podríamos utilizar esta función de extensión como si fuera una función normal de la clase String:

val myString = "hello"val upperCaseString = myString.toUppercase() // "HELLO"

Como puedes ver, las funciones de extensión nos permiten agregar nuevas funcionalidades a clases existentes de manera sencilla y conveniente.

Uso y diferencias de apply, also, with y run

Apply, also, with y run son funciones de alto nivel que se pueden utilizar para simplificar el código que utiliza un objeto en varias operaciones. Estas funciones se conocen como funciones de bloque y se utilizan para ejecutar un bloque de código con un objeto como receptor.

Veamos un ejemplo de cómo se pueden utilizar estas funciones:

classMyClass{
    var property1: String = "Hello"var property2: String = "World"
}

funmain() {
    val myObject = MyClass()

    // usando apply
    myObject.apply {
        property1 = "Goodbye"
        property2 = "Universe"
    }

    // usando also
    myObject.also {
        it.property1 = "Goodbye"
        it.property2 = "Universe"
    }

    // usando with
    with(myObject) {
        property1 = "Goodbye"
        property2 = "Universe"
    }

    // usando run
    myObject.run {
        property1 = "Goodbye"
        property2 = "Universe"
    }
}

En este ejemplo, todas estas funciones se utilizan para ejecutar un bloque de código con myObject como receptor. El bloque de código que se ejecuta cambia los valores de las propiedades property1 y property2 de myObject.

La diferencia entre estas funciones es lo que retornan. Apply y also devuelven el valor de retorno del objeto sobre el que se invocan, mientras que with y run devuelven el valor de retorno del bloque de código que se ejecuta con ellos.
Aquí hay un ejemplo más detallado de cómo se utilizan y qué retornan estas funciones:

classMyClass{
    var property1: String = "Hello"var property2: String = "World"
}

funmain() {
    val myObject = MyClass()

    // usando apply
    val result1 = myObject.apply {
        property1 = "Goodbye"
        property2 = "Universe"
    }
    println(result1) // imprime MyClass// usando also
    val result2 = myObject.also {
        it.property1 = "Goodbye"
        it.property2 = "Universe"
    }
    println(result2) // imprime MyClass// usando with
    val result3 = with(myObject) {
        property1 = "Goodbye"
        property2 = "Universe"
    }
    println(result3) // imprime MyClass// usando run
    val result4 = myObject.run {
        property1 = "Goodbye"
        property2 = "Universe"
    }
    println(result4) // imprime MyClass
}

En este ejemplo, todas estas funciones se utilizan para ejecutar un bloque de código con myObject como receptor.
El bloque de código que se ejecuta cambia los valores de las propiedades property1 y property2 de myObject.

En este ejemplo, result1, result2, result3 y result4 todos tienen el valor de retorno de myObject.

Aquí está un ejemplo sencillo en el que se utiliza el bloque que retorna ‘also’:

fun main() {
    val myList = mutableListOf(1, 2, 3)

    val result = myList.also {
        it.add(4)
        it.add(5)
        it.add(6)
    }

    println(result) // imprime [1, 2, 3, 4, 5, 6]
}

Sin embargo, es importante tener en cuenta que apply, also, with y run tienen diferentes usos y aplicaciones en el código Kotlin y debemos elegir la función adecuada para cada situación.
Veremos algunas aplicaciones prácticas de estas funciones en el código Kotlin real y aprenderemos a utilizarlas de manera efectiva para mejorar la legibilidad y la concisión de nuestro código.

Aplicaciones prácticas de apply, also, with y run

Ahora que hemos visto cómo funcionan y qué retornan apply, also, with y run, veamos algunas aplicaciones prácticas de estas funciones en el código Kotlin real.

Uno de los usos más comunes de apply es para inicializar y configurar objetos. Por ejemplo, podríamos utilizar apply para crear y configurar un LayoutParams de Android de la siguiente manera:

val layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT).apply {
    width = 100height = 200
    bottomMargin = 10
    leftMargin = 20
}

En este ejemplo, utilizamos apply para crear un nuevo LayoutParams y luego configurar sus propiedades width, height, bottomMargin y leftMargin en un solo bloque de código legible.

Otro uso común de apply es para ejecutar una serie de operaciones en un objeto sin tener que reasignar el resultado a una variable. Por ejemplo, podríamos utilizar apply para añadir varios elementos a una lista de la siguiente manera:

val myList = mutableListOf<Int>().apply {
    add(1)
    add(2)
    add(3)
}

En este ejemplo, utilizamos apply para crear una nueva lista mutable y luego agregar tres elementos a ella sin tener que reasignar el resultado a una variable.

Also se puede utilizar para realizar varias operaciones con un objeto sin afectar su estado final. Por ejemplo, podríamos utilizar also para imprimir una lista y luego invertir su orden de la siguiente manera:

val myList = listOf(1, 2, 3)

val result = myList.also {
    println(it) // imprime [1, 2, 3]
}.reversed()

println(result) // imprime [3, 2, 1]

En este ejemplo, utilizamos also para imprimir la lista y luego invertir su orden sin afectar la lista original.

With se puede utilizar para evitar tener que escribir repetidamente el nombre de un objeto al llamar a sus propiedades o métodos. Por ejemplo, podríamos utilizar with para añadir varios elementos a una lista de la siguiente manera:

val myList = mutableListOf()

with(myList) {
    add(1)
    add(2)
    add(3)
}

En este ejemplo, utilizamos with para llamar a varios métodos de myList sin tener que escribir repetidamente el nombre de la lista.

Otro uso común de with es para evitar tener que escribir repetidamente el nombre de un objeto al acceder a sus propiedades. Por ejemplo, podríamos utilizar with para imprimir el valor de varias propiedades de un objeto de la siguiente manera:

data classUser(val name: String, val age: Int)

val user = User("John", 30)

with(user) {
    println(name) // imprime John
    println(age) // imprime 30
}

En este ejemplo, utilizamos with para acceder a las propiedades name y age de user sin tener que escribir repetidamente el nombre del objeto.

Run se puede utilizar para ejecutar un bloque de código con un objeto como receptor y luego devolver el resultado de una expresión específica. Por ejemplo, podríamos utilizar run para calcular la suma de los elementos de una lista de la siguiente manera:

val myList = listOf(1, 2, 3, 4, 5)

val result = myList.run {
    var sum = 0for (i in this) {
        sum += i
    }
    sum
}

println(result) // imprime 15

En este ejemplo, utilizamos run para ejecutar un bloque de código que itera sobre los elementos de myList y calcula su suma. Luego, imprimimos el resultado de la suma.

Otro uso común de run es para ejecutar un bloque de código y luego devolver un valor de retorno específico. Por ejemplo, podríamos utilizar run para crear una nueva lista con elementos que cumplan cierta condición de la siguiente manera:

val myList = listOf(1, 2, 3, 4, 5)

val result = myList.run {
    val newList = mutableListOf<Int>()
    for (i in this) {
        if (i % 2 == 0) {
            newList.add(i)
        }
    }
    newList
}

println(result) // imprime [2, 4]

En este ejemplo, utilizamos run para ejecutar un bloque de código que itera sobre los elementos de myList y agrega solo los elementos pares a una nueva lista mutable. Luego, devolvemos la nueva lista mutable como el valor de retorno de run.

En conclusión, apply, also, with y run son funciones de extensión útiles y versátiles en Kotlin que nos permiten ejecutar bloques de código con un objeto como receptor y luego devolver diferentes valores de retorno según la situación. Cada una de estas funciones tiene su propio uso y aplicaciones en el código y debemos elegir la función adecuada para cada situación para mejorar la legibilidad y la concisión de nuestro código.

Así que la próxima vez que tengas que realizar varias operaciones con un objeto en Kotlin, recuerda que puedes utilizar apply, also, with o run para hacerlo de manera más efectiva y concisa. ¡Conviértete en un experto en el uso de estas funciones de extensión y toma el control de tu código Kotlin!

Escribe tu comentario
+ 2