Extension Functions (Funciones Extendidas)
Debido a que el uno de los principales objetivos de Kotlin (si es que no es el más importante) es permitir la integración con código preexistente, las funciones extendidas son muy importantes y uno de los temas más interesantes, ya que permiten crear funciones para clases “cerradas” y que sean llamadas de una manera que parezcan funciones de la misma clase.
Para entender mejor este tema, vamos a realizar un ejemplo:
Supongamos que queremos una función que para un string dado, te devuelva el mismo String pero con la primera letra mayúscula.
private fun String.capitalize(): String {
return when (this.isEmpty()) {
true -> this
false -> this[0].toUpperCase().plus(this.substring(1).toLowerCase())
}
}
Bueno vamos a explicar esta función:
Definimos una función con el nombre que deseemos, la clave está en String, con eso estamos definiendo que es una función de la clase String, y luego con la útil función when le decimos que si el String está vacío lo devuelva, caso contrario, hace la primera letra mayúscula, y lo concatena con el resto del String.
Para probar que la función esté trabajando correctamente, tenemos ciertos tests que nos permitirán asegurarnos de su correcto funcionamiento (si falta algún caso de prueba, su feedback es bienvenido). Como pueden ver la función se llama directo del String, sin tener que hacer uso de llamado de Clase.metodo como se suele hacer con las clases utilitarias.
@Test
fun shouldReturnCapitalizedString() {
val phrase = "george"
val expected = "George"
assertEquals(expected, phrase.customCapitalize())
}
@Test
fun shouldReturnEmptyStringWhenEmptyStringIsProvided(){
val phrase = ""
val expected = ""
assertEquals(expected, phrase.customCapitalize())
}
@Test
fun shouldReturnTheSameStringCapitalizedWhenTheProvidedStringHasOneCharacter(){
val phrase = "a"
val expected = "A"
assertEquals(expected, phrase.customCapitalize())
}
Si es de su agrado, pueden hacer los imports de los métodos concretos, para usar solo la función que quieran para evitar confusiones, como siempre la recomendación es hacer un código limpio, que permita a quien lo lea navegar por el sin problemas. Los imports serían algo así:
import strings.*
import strings.customCapitalize
import strings.customCapitalize as myMethodToCapitalize
Para el último caso, el uso sería con el nombre del alias:
assertEquals(expected, phrase.myMethodToCapitalize())
Como ya sabrán, Kotlin se usa mucho en interacción con Java, entonces si se quiere usar estas funciones desde código Java, lo que tenemos que hacer es llamarlas como un estático, es decir Clase.metodo, ya que para Java las funciones de alto nivel de Kotlin, se compilan solo como clases y métodos estáticos.
Estas funciones no se pueden sobre escribir, si quieres distintas implementaciones para el mismo método en clases heredadas, se debe crear la función extendida para cada clase, esto debido a que estas funciones no son parte de las clases, son funciones externas a ellas.
Estas funciones son muy útiles y ahorran mucho tiempo, ya que pueden ser usadas dentro de lambdas, o en cualquier contexto que sea de tu interés.
Espero que te sea de ayuda y como siempre, su feeback es bienvenido.