Sobrecarga de operadores en Kotlin. Añade operaciones estándar a cualquier clase (KDA 17)
Antonio Leiva

En Kotlin, como en todo lenguaje, tenemos operadores predefinidos para realizar ciertas operaciones.

Los más típicos son la suma (+), resta (-), multiplicación (*) o división (/), pero hay unos cuantos más.

En algunos lenguajes, como en Java, estos operadores están limitados a ciertos tipos de datos, y no tenemos forma de hacer que otros tipos los utilicen.

Hay otros lenguajes como Scala en los que nos podemos inventar cualquier tipo de operador que se nos ocurra, ya que los nombres de las funciones aceptan cualquier símbolo.

En Kotlin se toma una solución intermedia: hay una serie de operadores predefinidos, pero los podemos sobrecargar para cualquier tipo de datos.

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

Sobrecarga de operadores en Kotlin

Como hablábamos, en Kotlin se pueden sobrecargar cierto número de operadores, implementando la función correspondiente en nuestra clase. Esa función debe ser marcada con la palabra reservada operator.

Los operadores son básicamente los siguientes:

Operadores Unarios

+aa.unaryPlus()
-aa.unaryMinus()
!aa.not()
a++a.inc()
a–a.dec()

Operadores Binarios

a + ba.plus(b)
a – ba.minus(b)
a * ba.times(b)
a / ba.div(b)
a % ba.mod(b)
a..ba.rangeTo(b)
a in bb.contains(a)
a !in b!b.contains(a)
a += ba.plusAssign(b)
a -= ba.minusAssign(b)
a *= ba.timesAssign(b)
a /= ba.divAssign(b)
a %= ba.modAssign(b)

Operadores tipo array

a[i]a.get(i)
a[i, j]a.get(i, j)
a[i_1, …, i_n]a.get(i_1, …, i_n)
a[i] = ba.set(i, b)
a[i, j] = ba.set(i, j, b)
a[i_1, …, i_n] = ba.set(i_1, …, i_n, b)

Operación Equals

a == ba?.equals(b) ?: b === null
a != b!(a?.equals(b) ?: b === null)

Las operaciones equals son un poco diferentes, porque usan una traducción más compleja para hacer un chequeo correcto, y porque esperan una especificación exacta de la función, y no sólo un nombre específico para la misma. La función debe ser implementada exactamente así:

fun equals(other: Any?): Boolean

Invocación de funciones

a(i)a.invoke(i)
a(i, j)a.invoke(i, j)
a(i_1, …, i_n)a.invoke(i_1, …, i_n)

Un ejemplo

Imagina que tienes un modelo de datos que son compañías, cada una de las cuales tiene un listado de empleados.

Podrías utilizar el operador get para acceder a las posiciones mediante corchetes. La implementación es muy sencilla:

class Employee(val id: Long, val name: String)

class Company(private val employees: List) {
    operator fun get(pos: Int) = employees[pos]
}

Y así es como podrías usarlo:

val company = Company(listOf(Employee(1235, "John"), Employee(2584, "Mike")))
val mike = company[1]

Pero podrías ir más, allá, y usar el id para recuperar el valor, implementando la función así:

operator fun get(id: Long) = employees.first { it.id == id }

val mike = company[2584]

Conclusión

Los operadores nos pueden ayudar a dar mayor legibilidad utilizando símbolos comunes para operaciones conocidas.

Hay que tener cuidado con no utilizarlos en situaciones en las que pueda llevar a confusión a las personas que lo lean, pero se pueden convertir en una herramienta realmente interesante.

Si todo esto te apasiona tanto como a mí, te animo a que te apuntes a mi 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…

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...

Cómo hacer tests de Corrutinas y Flows – Paso a Paso

Cómo hacer tests de Corrutinas y Flows – Paso a Paso

¡Vaya viaje por el que hemos pasado en estos artículos! Hace ya varios de ellos empezamos hablando sobre la programación reactiva con Flow, y hemos aprendido un montón de conceptos e ideas sobre cómo aplicarlos en el día a día. Pero nada de esto está completo si no...

Convertir cualquier callback en un Flow con CallbackFlow

Convertir cualquier callback en un Flow con CallbackFlow

Existen varios tipos de Flows muy particulares que nos van a solucionar la vida cuando tengamos que hacer cosas muy concretas. Ya vimos StateFlow en un artículo anterior, y en esta ocasión hablamos de CallbackFlow ¿Qué es CallbackFlow? Es un tipo de Flow que nos...