En este tutorial aprenderás a como declarar funciones de extensión en Kotlin, con el fin de añadir funcionalidades extras a tus clases o las de otras personas.
Declarar Funciones De Extensión
Una función de extensión es una función que extiende las funcionalidades de una clase, con la introducción de un nuevo parámetro llamado: parámetro recibidor.
Este parámetro se incorpora a la sintaxis, declarando su tipo, seguido de un punto y luego el nombre de la función (TipoRecibidor.nombre()
).
En otras palabras, una función de extensión es una función que puede ser llamada como miembro de una clase, pero está definida por fuera de ella.
Ejemplo:
Supongamos que deseamos convertir resultados booleanos a las palabras SI y NO. La solución con una función de extensión sería así:
fun Boolean.adverb() = if (this) "SI" else "NO"
La función de extensión adverb()
usa como tipo recibidor a Boolean
. En su cuerpo puede acceder a this
para referirse al objeto recibidor. Este te permitirá acceder a los miembros de los objetos que usarán esta función.
Puedes hacer una llamada de función regular con cualquier ejemplar de la clase Boolean
. Por ejemplo:
fun main() {
val a = 4
val b = 3
val res = (a > b).adverb()
print("¿$a es mayor que $b?: $res")
}
Resultado:
¿4 es mayor que 3?: SI
Ejemplo De Función De Extensión
Tomemos una pequeña referencia sobre cursos y estudiantes en una universidad.
Para ello se crea la clase Student
con el nombre y edad de los estudiantes. Y también la clase Course
para representar a los cursos, a los cuales se les han asignado estudiantes.
class Student(val name: String, val age: Int)
class Course(val students: List<Student>)
Ahora, queremos hacer dos consultas:
- Obtener la edad del estudiante con mayor edad en el curso
- Determinar el número de estudiantes cuyo nombre comienza por la inicial que se especifique.
Como no queremos mezclar a las entidades con esta funcionalidad, crearemos las siguientes funciones de extensión:
fun Course.olderStudentAge(): Int {
return students.maxOf { it.age }
}
fun Course.studentsWithInitial(initial: Char): Int {
return students.filter { it.name[0] == initial }.size
}
Course.olderStudentAge()
accede a la propiedad students
de Course
y llama a su función maxOf()
, la cual obtiene el valor máximo de la lista de valores, teniendo en cuenta el predicado.
Course.studentsWithInitial()
, recibe la inicial del nombre como parámetro y usa la función filter()
sobre la lista de estudiantes del curso, con el fin de obtener el tamaño (size
) de la lista filtrada.
Prueba:
fun main() {
val course = Course(listOf(
Student("María", 17),
Student("Rupertina", 25),
Student("Ricardina", 18)
))
println("La mayor tiene ${course.olderStudentAge()}")
println("Estudiantes cuyo nombre empieza con R: " +
"${course.studentsWithInitial('R')}")
}
Resultado:
Estudiante mayor: 25
Estudiantes cuyo nombre empieza con R: 2
Nota: No usamos la expresión this
ya que disponemos del objeto recibidor en el contexto de la función de extensión y es redundante. Es por eso que students
puede ser llamada como si estuvieras al interior de la clase Course
.
Por último puedes reducir las funciones de extensión a una sintaxis de única expresión.
fun Course.olderStudentAge() = students.maxOf { it.age }
fun Course.studentsWithInitial(initial: Char) =
students.filter {
it.name[0] == initial
}.size