La Función with En Kotlin

En este tutorial verás la definición y uso de la función with en Kotlin, para ejecutar un bloque de código sobre un objeto recibidor.

La Función with

La función with es otra de las funciones de alcance proveídas por la librería estándar de Kotlin. Su objetivo es ayudarte a simplificar el uso de múltiples operaciones sobre un objeto:

inline fun <T, R> with(receiver: T, block: T.() -> R): R

with toma como primer parámetro al objeto receiver y al tipo función block. De esta forma las sentencias de block son aplicadas sobre receiver y el resultado final será R.

with(objetoAUsar){
    // acceso a propiedades, ejecución de métodos miembro, etc.
}

Aunque la función provee un resultado, JetBrains recomienda ejecutarla para aislar las acciones sobre el contexto de un objeto y no tanto para especificar el resultado en la lambda pasada como argumento.

Ejemplo Con Función with

Para representar el uso de la función with en Kotlin, usaremos una clase de datos llamada Rect, la cual es el diseño de un rectángulo que será visualizado en pantalla.

Sus propiedades son: x e y para la posición en un plano coordenado de dos dimensiones; y ancho junto a la altura para expresar el área ocupada en cada eje.

data class Rect(
    var x: Float,
    var y: Float,
    var width: Float,
    var height: Float
)

Ahora creamos una instancia con valores iniciales (0, 0, 10, 10). Luego suponemos que debido a una deformidad en la simulación de físicas, queremos actualizar sus propiedades a (5, 6, 3 ,3).

En código tendríamos:

fun main() {
    val wall1 = Rect(0f, 0f, 10f, 10f)

    // Deformidades por lógica del mundo físico

    wall1.x = 5f
    wall1.y = 6f
    wall1.width = 3f
    wall1.height = 3f

    print(wall1)
}

Como notas, accederías a cada propiedad con el punto después del nombre de la instancia como es costumbre.

Sin embargo, con la función with es posible pasar a wall1 como objeto recibidor y aplicar cada asignación omitiendo el nombre.

fun main() {
    val wall1 = Rect(0f, 0f, 10f, 10f)

    with(wall1) {
        x = 5f
        y = 6f
        width = 3f
        height = 3f
    }

    print(wall1)
}

Recuerda que podemos omitir los paréntesis del parámetro block de with y cambiarlo por la función lambda directamente, ya que es el último parámetro en la firma.

Con eso en mente, el lambda con recibidor te permite acceder al objeto wall1 y modificar sus propiedades. Esto mejora la legibilidad del bloque de código y acorta cada expresión.

Cabe resaltar que with es similar a run, solo que run es una función de extensión. Esto permite usar el operador de acceso seguro en el caso de que wall1 estuviese definido con el tipo anulable Rect?:

wall1?.run{
    x = 5f
    y = 6f
    width = 3f
    height = 3f
}

Únete Al Discord De Develou

Si tienes problemas con el código de este tutorial, preguntas, recomendaciones o solo deseas discutir sobre desarrollo Android conmigo y otros desarrolladores, únete a la comunidad de Discord de Develou y siéntete libre de participar como gustes. ¡Te espero!