Funciones de extensión en Kotlin: Extiende el Framework de Android (KDA 08)
Antonio Leiva

Tenemos que admitir que el Framework de Android a veces nos pone las cosas un poco difíciles, y en Java la única solución que nos queda es crear wrappers que hagan las cosas como nosotros queremos, lo que muchas veces es demasiado complejo para lo que queremos.

¿Qué te parecería poder añadir funciones extra a las clases del Framework? Esto es lo que nos permiten las funciones de extensión de Kotlin.

¿Te gustaría comenzar hoy a dar el siguiente paso? Te recomiendo que entres en mi training gratuito aquí.

Training Revienta tu productividad en Android con Kotlin

Funciones de extensión en Kotlin

Las funciones de extensión (o extension functions en inglés) son funciones que, como su propio nombre indica, nos ayudan a extender la funcionalidad de clases sin necesidad de tocar su código. Ahora vamos a ver cómo se definen estas funciones, y algunos ejemplos que a mí personalmente me resultan muy útiles.

¿Cómo se define una función de extensión?

Tan solo hay que escribir una función como lo harías normalmente, y ponerle delante el nombre de la clase separado por un punto.

Ejemplo muy sencillo: queremos hacer que una vista tenga la función visible(), que la hace visible. Escribiríamos algo como esto:

fun View.visible() {
    this.visibility = View.VISIBLE
}

El this  lo he puesto para que veas que podemos usar las funciones y propiedades de esa clase como si estuviéramos dentro de  la propia clase, pero lo puedes omitir:

fun View.visible() {
    visibility = View.VISIBLE
}

Algunos ejemplos interesantes

Hay un par de ejemplos que me gusta poner, porque resumen muy bien la potencialidad de esto.

El primero es cuando estás inflando una vista dentro de un adapter. Normalmente utilizarías algo así:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val v = LayoutInflater.from(parent.context).inflate(R.layout.view_item, parent, false)
    return ViewHolder(v)
}

La línea que infla la vista y usa el parent es demasiado compleja, y el 99% de las veces suele ser igual en cualquier adapter. ¿Por qué no hacer que los ViewGroup  puedan inflar vistas?

fun ViewGroup.inflate(layoutRes: Int): View {
    return LayoutInflater.from(context).inflate(layoutRes, this, false)
}

Ahora ya puedes utilizarlo en el código de arriba:

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
    val v = parent.inflate(R.layout.view_item)
    return ViewHolder(v)
}

Un ejemplo muy parecido se puede hacer con las imágenes. Si utilizas por ejemplo la librería de Picasso, necesitas andar haciendo el típico ritual:

Picasso.with(imageView.context).load(url).into(imageView)

¿Qué te parecería poder decirle a ImageView que cargue una url directamente?

fun ImageView.loadUrl(url: String) {
    Picasso.with(context).load(url).into(this)
}

imageView.loadUrl(url)

Propiedades de extensión

Igual que puedes hacer funciones de extensión, lo mismo puedes hacer con properties. Lo único que no podrán guardar un estado propio, sino valerse de las funciones ya existentes para modificar el estado:

val ViewGroup.children: List
    get() = (0..childCount -1).map { getChildAt(it) }

Esta property recupera los hijos de un ViewGroup

Ahora podrías iterar sobre ellos directamente:

parent.children.forEach { it.visible() }

Nota: it es una palabra reservada que se utiliza para acceder al valor de entrada de la función, cuando solo hay uno. Como ya hemos visto en otros artículos, se pueden nombrar esos valores de entrada, y asignar más cuando hay más de uno.

Conclusión

Con las funciones y las propiedades de extensión puedes extender cualquier librería a la que no tengas acceso y luego utilizar esas funciones y propiedades como si fueran propias de la clase. Lo único que verás es un import extra en el archivo en el que se use.

Si de verdad vas en serio con Kotlin y, como yo, piensas que es el lenguaje del futuro en Android, te recomiendo que le eches un vistazo al training gratuito, donde te contaré todo lo que necesitas para aprender a crear tus Apps Android en Kotlin desde cero.

Quizá también te interese…

Kotlin 1.5.0 : Las 5 novedades que puedes empezar a usar hoy

Kotlin 1.5.0 : Las 5 novedades que puedes empezar a usar hoy

Kotlin 1.5.0 ya está aquí, y como siempre trae una serie de novedades que te van a interesar muchísimo. Cabe destacar que a partir de ahora, de acuerdo las nuevas versiones de Kotlin se lanzarán cada 6 meses, independientemente de las nuevas funcionalidades que...

¿Qué es Kotlin y para qué sirve?

¿Qué es Kotlin y para qué sirve?

Kotlin es un lenguaje de programación de código abierto creado por JetBrains que se ha popularizado gracias a que se puede utilizar para programar aplicaciones Android. Pero si has llegado hasta aquí pensando que Kotlin solo se puede usar en Android, lo que te voy a...

2 formas de recolectar Flows en la UI que SÍ funcionan

2 formas de recolectar Flows en la UI que SÍ funcionan

En la serie de artículos sobre Programación Reactiva con Flow hemos visto muchos conceptos, y hemos aprendido cómo aplicarlos al desarrollo Android. Pero hay algo que no hemos hecho del todo bien. Esto es la recolección de Flows desde la Activity (o el Fragment, en...

2 Comentarios

  1. Luis Angel

    Hola, sólo tengo un par de dudas:

    ¿Las funciones de extensión son como las extensiones de Swift?

    ¿Qué alcance tienen las funciones de extensión y dónde deberían declararse?

    ¿Las funciones de extensión aplican igual a las clases hijas?

    ¿Qué pasa si una clase hija ya tiene una función con la misma firma, existe algún conflicto o se sobreescribe?

    ¿Qué diferencia hay entre extender un atributo y una función? Por ejemplo, podria ser una función llamada getChilds()

    Gracias!

    Responder
    • Antonio Leiva

      – No conozco Swift, pero por lo que sé de oídas, entiendo que sí
      – Si las funciones son públicas (que es la visibilidad por defecto en Kotlin), las puedes usar desde cualquier sitio. Normalmente se crean archivos de extensiones que aplican a una clase o conjunto de clases. Es el equivalente a los utils de Java, así que la forma de estructurarlos es muy similar.
      – Si una clase ya tiene una función que se llama igual que la de extensión, cuando defines la función de extensión te muestra un warning indicando que se usará la original. No puedes sobrescribir una función existente.
      – Es semántica nada más. En Kotlin no se suele usar el concepto de getter y setter (recuerda las properties), y por tanto normalmente no escribirías getChilds(), sino childs. Así que ahí es mejor usar una property. Pero su utilidad es la misma.

      Responder

Enviar un comentario

Los datos personales que proporciones a través de este formulario quedarán registrados en un fichero de Antonio Leiva Gordillo, con el fin de gestionar los comentarios que realizas en este blog. La legitimación se realiza a través del consentimiento de la parte interesada. Si no se acepta, no podrás comentar en este blog. Los datos que proporciona solo se utilizan para evitar el correo no deseado y no se usarán para nada más. Puede ejercer los derechos de acceso, rectificación, cancelación y oposición en contacto@devexperto.com.

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Acepto la política de privacidad *