Icono del sitio Develou

Funciones De Extensión En Kotlin

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:

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
Salir de la versión móvil