Cómo crear y usar funciones en Kotlin

1. Antes de comenzar

En un codelab anterior, viste un programa simple que imprimió Hello, world!. En los programas que escribiste hasta ahora, viste las siguientes dos funciones:

  • Una función main(), que es obligatoria en todos los programas en Kotlin. Es el punto de entrada, o punto de partida, del programa.
  • Una función println(), a la que llamaste desde main() para generar texto.

En este codelab, aprenderás más sobre las funciones.

Las funciones te permiten dividir tu código en partes reutilizables, en lugar de incluir todo en main(). Las funciones son un componente fundamental en las apps para Android, y aprender a definirlas y usarlas es un paso importante en tu recorrido para convertirte en desarrollador de Android.

Requisitos previos

  • Conocimientos de los conceptos básicos de programación de Kotlin, incluidas las variables, y las funciones println() y main()

Qué aprenderás

  • Cómo definir y llamar a tus propias funciones.
  • Cómo mostrar los valores de una función que puedes almacenar en una variable.
  • Cómo definir y llamar a funciones con varios parámetros.
  • Cómo llamar a funciones con argumentos con nombre.
  • Cómo establecer valores predeterminados para los parámetros de la función.

Requisitos

  • Un navegador web con acceso a Playground de Kotlin

2. Cómo definir una función y cómo llamarla

Antes de explorar las funciones en profundidad, revisemos la terminología básica.

  • Declarar (o definir) una función usa la palabra clave fun e incluye código dentro de las llaves que contiene las instrucciones necesarias para ejecutar una tarea.
  • Llamar a una función causa que se ejecute todo el código dentro esta.

Hasta ahora, escribiste todo el código en la función main(). En realidad, en ninguna parte del código se llama a la función main(); el compilador de Kotlin la usa como punto de partida. La función main() está diseñada para incluir solo otro código que desees ejecutar, como llamadas a la función println().

La función println() es parte del lenguaje Kotlin. Sin embargo, puedes definir tus propias funciones. De esta manera, se permite reutilizar tu código si necesitas llamarlo más de una vez. Considera el siguiente programa como ejemplo.

fun main() {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}

La función main() consta de dos declaraciones println(): una para desearle un feliz cumpleaños a Rover y otra que indica su edad.

Si bien Kotlin te permite colocar todo el código en la función main(), es posible que no siempre desees hacerlo. Por ejemplo, si también quieres que tu programa contenga un saludo de Año Nuevo, la función main también deberá incluir esas llamadas a println(). O bien, es posible que quieras saludar a Rover varias veces. Simplemente, puedes copiar y pegar el código o crear una función diferente para el saludo de cumpleaños. Harás lo último. Crear funciones diferentes para tareas específicas tiene una serie de beneficios.

  • Código reutilizable: En lugar de copiar y pegar el código que necesitas usar más de una vez, simplemente puedes llamar a una función cuando sea necesario.
  • Legibilidad: Garantizar que las funciones realicen una única tarea específica permite que otros desarrolladores y compañeros de equipo, así como tú mismo en el futuro, sepan con exactitud qué hace un fragmento de código.

La sintaxis para definir una función se muestra en el siguiente diagrama.

Sintaxis para definir una función

La definición de una función comienza con la palabra clave fun, seguida del nombre de la función, un conjunto de paréntesis de apertura y cierre, y un conjunto de llaves de apertura y cierre. Entre llaves, se muestra el código que se ejecutará cuando se llame a la función.

Crearás una función nueva para quitar las dos declaraciones println() de la función main().

  1. En tu navegador, abre el Playground de Kotlin y reemplaza el contenido con el siguiente código.
fun main() {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}
  1. Después de la función main(), define una nueva función llamada birthdayGreeting(). Esta función se declara con la misma sintaxis que la función main().
fun main() {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}

fun birthdayGreeting() {

}
  1. Mueve las dos declaraciones println() de main() a las llaves de la función birthdayGreeting().
fun main() {

}

fun birthdayGreeting() {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}
  1. En la función main(), llama a la función birthdayGreeting(). El código finalizado debería verse de la siguiente manera:
fun main() {
    birthdayGreeting()
}

fun birthdayGreeting() {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}
  1. Ejecuta tu código. Debería verse el siguiente resultado:
Happy Birthday, Rover!
You are now 5 years old!

3. Cómo mostrar un valor de una función

En apps más complejas, las funciones no se limitan a imprimir texto.

Las funciones de Kotlin pueden generar datos que se denominan valor de muestra que se almacenan en una variable que puedes usar en cualquier otra parte del código.

Cuando defines una función, puedes especificar el tipo de datos del valor que deseas que se muestre. Para especificar el tipo de datos que se devuelve, debes colocar dos puntos (:) después de los paréntesis, un solo espacio en blanco y, luego, el nombre del tipo (Int, String, etc.). A continuación, se coloca un solo espacio entre el tipo de datos que se devuelve y la llave de apertura. Dentro del cuerpo de la función, después de todas las sentencias, usa una sentencia return para especificar el valor que desea que muestre la función. Una sentencia return consiste en la palabra clave return, seguida del valor, como una variable, que quieres que muestre la función como resultado.

La sintaxis para declarar una función con un tipo de datos que se devuelve es la siguiente.

Sintaxis para declarar una función con un tipo de datos que se devuelve

El tipo Unit

De forma predeterminada, si no se especifica un tipo de datos que se muestra, el predeterminado es Unit. Unit significa que la función no muestra ningún valor. Unit es equivalente a los tipos nulos de datos que se muestran en otros lenguajes (void en Java y C, tupla Void/vacía () en Swift; None en Python, etc.). Cualquier función que no muestre un valor muestra Unit de forma implícita. Si deseas observar este comportamiento, modifica tu código para que muestre Unit.

  1. En la declaración de la función para birthdayGreeting(), agrega dos puntos después del paréntesis de cierre y especifica el tipo de datos que se muestra como Unit.
fun main() {
    birthdayGreeting()
}

fun birthdayGreeting(): Unit {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}
  1. Ejecuta el código y observa que todo continúa funcionando.
Happy Birthday, Rover!
You are now 5 years old!

Es opcional especificar el tipo de datos que se muestra de Unit en Kotlin. Para las funciones que no muestran nada o que muestran Unit, no necesitas una sentencia return.

Cómo mostrar String de birthdayGreeting()

A fin de demostrar cómo una función puede mostrar un valor, deberás modificar la función birthdayGreeting() para que muestre una string, en lugar de simplemente imprimir el resultado.

  1. Reemplaza el tipo de datos que se muestra Unit por String.
fun birthdayGreeting(): String {
    println("Happy Birthday, Rover!")
    println("You are now 5 years old!")
}
  1. Ejecuta tu código. Se mostrará un error. Si declaras un tipo de datos que se muestra para una función (p. ej., String), esa función debe incluir una sentencia return.
A 'return' expression required in a function with a block body ('{...}')
  1. Solo puedes mostrar una cadena de una función, no dos. Reemplaza las sentencias println() por dos variables, nameGreeting y ageGreeting, con la palabra clave val. Como quitaste las llamadas a println() de birthdayGreeting(), llamar a birthdayGreeting() no imprimirá nada.
fun birthdayGreeting(): String {
    val nameGreeting = "Happy Birthday, Rover!"
    val ageGreeting = "You are now 5 years old!"
}
  1. Con la string que le da formato a la sintaxis que aprendiste en un codelab anterior, agrega una sentencia return para mostrar una string de la función que incluye ambos saludos.

Para dar formato a los saludos en una línea separada, también debes usar el carácter de escape \n. Es similar al carácter de escape \" que aprendiste en un codelab anterior. El carácter \n se reemplaza por una línea nueva, de modo que los dos saludos estén en una línea separada.

fun birthdayGreeting(): String {
    val nameGreeting = "Happy Birthday, Rover!"
    val ageGreeting = "You are now 5 years old!"
    return "$nameGreeting\n$ageGreeting"
}
  1. En main(), dado que birthdayGreeting() muestra un valor, puedes almacenar el resultado en una variable de string. Declara una variable greeting mediante val para almacenar el resultado de la llamada a birthdayGreeting().
fun main() {
    val greeting = birthdayGreeting()
}
  1. En main(), llama a println() para imprimir la string greeting. La función main() ahora debería verse de la siguiente manera:
fun main() {
    val greeting = birthdayGreeting()
    println(greeting)
}
  1. Ejecuta tu código y, luego, observa que el resultado sea el mismo que antes: Mostrar un valor te permite almacenar el resultado en una variable, pero ¿qué crees que sucede si llamas a la función birthdayGreeting() dentro de la función println()?
Happy Birthday, Rover!
You are now 5 years old!
  1. Quita la variable y, luego, pasa el resultado de la llamada a la función birthdayGreeting() a la función println():
fun main() {
    println(birthdayGreeting())
}
  1. Ejecuta tu código y observa el resultado. El valor de muestra de la llamada a birthdayGreeting() se pasa directamente a println().
Happy Birthday, Rover!
You are now 5 years old!

4. Cómo agregar un parámetro a la función birthdayGreeting()

Como viste, cuando llamas a la función println(), puedes incluir una string entre paréntesis o pasar un valor a la función. Puedes hacer lo mismo con la función birthdayGreeting(). Sin embargo, primero debes agregar un parámetro a birthdayGreeting().

Un parámetro especifica el nombre de una variable y un tipo de datos que puedes pasar a una función como datos para acceder dentro de esta. Los parámetros se declaran entre paréntesis después del nombre de la función.

Sintaxis para declarar una función con parámetros y un tipo de datos que se devuelve

Cada parámetro consiste en un nombre de variable y un tipo de datos, separados por dos puntos y un espacio. Si hay varios parámetros, se separan con una coma.

Por el momento, la función birthdayGreeting() solo se puede usar para saludar a Rover. Agregarás un parámetro a la función birthdayGreeting() para que puedas saludar con cualquier nombre que pases a la función.

  1. Dentro de los paréntesis de la función birthdayGreeting(), agrega un parámetro name de tipo String con la sintaxis name: String.
fun birthdayGreeting(name: String): String {
    val nameGreeting = "Happy Birthday, Rover!"
    val ageGreeting = "You are now 5 years old!"
    return "$nameGreeting\n$ageGreeting"
}

El parámetro definido en el paso anterior funciona como una variable declarada con la palabra clave val. Su valor se puede usar en cualquier parte de la función birthdayGreeting(). En un codelab anterior, aprendiste cómo insertar el valor de una variable en una string.

  1. Reemplaza Rover en la string nameGreeting por el símbolo $ seguido del parámetro name.
fun birthdayGreeting(name: String): String {
    val nameGreeting = "Happy Birthday, $name!"
    val ageGreeting = "You are now 5 years old!"
    return "$nameGreeting\n$ageGreeting"
}
  1. Ejecuta tu código y observa el error. Ahora que declaraste el parámetro name, debes pasar un String cuando llames a birthdayGreeting(). Cuando llamas a una función que toma un parámetro, debes pasar un argumento a la función. El argumento es el valor que pasas, como "Rover".
No value passed for parameter 'name'
  1. Pasa "Rover" a la llamada birthdayGreeting() en main().
fun main() {
    println(birthdayGreeting("Rover"))
}
  1. Ejecuta tu código y observa el resultado. El nombre Rover proviene del parámetro name.
Happy Birthday, Rover!
You are now 5 years old!
  1. Como birthdayGreeting() toma un parámetro, puedes llamarlo con un nombre que no sea Rover. Agrega otra llamada a birthdayGreeting() dentro de la llamada a println() y pasa el argumento "Rex".
println(birthdayGreeting("Rover"))
println(birthdayGreeting("Rex"))
  1. Vuelve a ejecutar el código y, luego, observa que el resultado difiere en función del argumento que se pasó a birthdayGreeting().
Happy Birthday, Rover!
You are now 5 years old!
Happy Birthday, Rex!
You are now 5 years old!

5. Funciones con varios parámetros

Anteriormente, agregaste un parámetro para cambiar el saludo según el nombre. Sin embargo, también puedes definir más de un parámetro para una función, incluso parámetros de diferentes tipos de datos. En esta sección, modificarás el saludo de modo que también cambie en función de la edad del perro.

Función con varios parámetros

Las definiciones de los parámetros están separadas con comas. De manera similar, cuando llamas a una función con varios parámetros, también separas los argumentos que se pasaron con comas. Veamos esto en acción.

  1. Después del parámetro name, agrega un parámetro age de tipo Int a la función birthdayGreeting(). La declaración de la función nueva debe tener los dos parámetros, name y age, separados con comas:
fun birthdayGreeting(name: String, age: Int): String {
    val nameGreeting = "Happy Birthday, $name!"
    val ageGreeting = "You are now 5 years old!"
    return "$nameGreeting\n$ageGreeting"
}
  1. La nueva string de saludo debe usar el parámetro age. Actualiza la función birthdayGreeting() para usar el valor del parámetro age en la string ageGreeting.
fun birthdayGreeting(name: String, age: Int): String {
    val nameGreeting = "Happy Birthday, $name!"
    val ageGreeting = "You are now $age years old!"
    return "$nameGreeting\n$ageGreeting"
}
  1. Ejecuta la función y, luego, observa los errores en el resultado:
No value passed for parameter 'age'
No value passed for parameter 'age'
  1. Modifica las dos llamadas a la función birthdayGreeting() en main() a fin de pasar una edad diferente para cada perro. Pasa 5 para la edad de Rover y 2 para la edad de Rex.
fun main() {
    println(birthdayGreeting("Rover", 5))
    println(birthdayGreeting("Rex", 2))
}
  1. Ejecuta tu código. Ahora que pasaste los valores para ambos parámetros, el resultado debería reflejar el nombre y la edad de cada perro cuando llames a la función.
Happy Birthday, Rover!
You are now 5 years old!
Happy Birthday, Rex!
You are now 2 years old!

Firma de la función

Hasta ahora, viste cómo definir el nombre de la función, las entradas (parámetros) y los resultados. El nombre de la función y sus entradas (parámetros) se conocen colectivamente como firma de la función. La firma de la función consta de todo lo que está antes del tipo de datos que se muestra y se indica en el siguiente fragmento de código.

fun birthdayGreeting(name: String, age: Int)

A veces, los parámetros separados con comas se denominan lista de parámetros.

Con frecuencia, verás estos términos en la documentación para código que escriben otros desarrolladores. La firma de la función te indica el nombre de la función y los tipos de datos que se pueden pasar.

Ahora aprendiste un montón sobre la sintaxis nueva para definir funciones. Consulta el siguiente diagrama para obtener un resumen de la sintaxis de las funciones.

Diagrama de resumen de la sintaxis de las funciones

6. Argumentos con nombre

En los ejemplos anteriores, no tuviste que especificar los nombres de los parámetros, name o age, cuando llamaste a una función. Sin embargo, podrás hacerlo si así lo decides. Por ejemplo, puedes llamar a una función con muchos parámetros o pasar los argumentos en un orden diferente; por ejemplo, colocar el parámetro age antes del parámetro name. Cuando incluyes un nombre de parámetro si llamas a una función, esta se denomina argumento con nombre. Intenta usar un argumento con nombre con la función birthdayGreeting().

  1. Modifica la llamada para que Rex use argumentos con nombre como se muestra en este fragmento de código. Para ello, incluye el nombre del parámetro seguido de un signo igual y, luego, el valor (p. ej., name = "Rex").
println(birthdayGreeting(name = "Rex", age = 2))
  1. Ejecuta el código y, luego, observa que el resultado no haya cambiado:
Happy Birthday, Rover!
You are now 5 years old!
Happy Birthday, Rex!
You are now 2 years old!
  1. Reordena los argumentos con nombres. Por ejemplo, coloca el argumento con nombre age antes del argumento con nombre name.
println(birthdayGreeting(age = 2, name = "Rex"))
  1. Ejecuta el código y observa que el resultado sigue siendo el mismo. Si bien cambiaste el orden de los argumentos, se pasan los mismos valores para los mismos parámetros.
Happy Birthday, Rover!
You are now 5 years old!
Happy Birthday, Rex!
You are now 2 years old!

7. Argumentos predeterminados

Los parámetros de la función también pueden especificar argumentos predeterminados. Quizás Rover es tu perro favorito, o esperas que se llame a una función con argumentos específicos en la mayoría de los casos. Cuando llamas a una función, puedes decidir omitir los argumentos para los que haya un valor predeterminado, en cuyo caso se usa el predeterminado.

Para agregar un argumento predeterminado, agrega un operador de asignación (=) después del tipo de datos para el parámetro y configúralo del mismo modo que a un valor. Modifica tu código para usar un argumento predeterminado.

  1. En la función birthdayGreeting(), establece el parámetro name en el valor predeterminado "Rover".
fun birthdayGreeting(name: String = "Rover", age: Int): String {
    return "Happy Birthday, $name! You are now $age years old!"
}
  1. En la primera llamada a birthdayGreeting() para Rover en main(), establece el argumento con nombre age en 5. Como el parámetro age se define después de name, debes usar el argumento con nombre age. Sin los argumentos con nombre, Kotlin supone que el orden de los argumentos es el mismo en el que se definen los parámetros. El argumento con nombre se usa a fin de garantizar que Kotlin espere un Int para el parámetro age.
println(birthdayGreeting(age = 5))
println(birthdayGreeting("Rex", 2))
  1. Ejecuta tu código. La primera llamada a la función birthdayGreeting() muestra "Rover" como nombre porque nunca lo especificaste. La segunda llamada a birthdayGreeting() todavía usa el valor Rex, que pasaste para name.
Happy Birthday, Rover! You are now 5 years old!
Happy Birthday, Rex! You are now 2 years old!
  1. Quita el nombre de la segunda llamada a la función birthdayGreeting(). Una vez más, debido a que se omite name, debes usar un argumento con nombre para la edad.
println(birthdayGreeting(age = 5))
println(birthdayGreeting(age = 2))
  1. Ejecuta tu código. Luego, observa que ambas llamadas a birthdayGreeting() imprimen "Rover" como nombre porque no se pasa ningún argumento con nombre.
Happy Birthday, Rover! You are now 5 years old!
Happy Birthday, Rover! You are now 2 years old!

8. Conclusión

¡Felicitaciones! Aprendiste a definir funciones en Kotlin y a llamarlas.

Resumen

  • Las funciones se definen con la palabra clave fun y contienen fragmentos de código reutilizables.
  • Las funciones facilitan el mantenimiento de los programas más grandes y evitan la repetición innecesaria de código.
  • Las funciones pueden mostrar un valor que puedes almacenar en una variable para usarlo más tarde.
  • Las funciones pueden tomar parámetros, que son variables disponibles dentro del cuerpo de una función.
  • Los argumentos son los valores que pasas cuando llamas a una función.
  • Puedes nombrar argumentos cuando llamas a una función. Cuando usas argumentos con nombre, puedes reordenarlos sin afectar el resultado.
  • Puedes especificar un argumento predeterminado que te permita omitirlo cuando llames a una función.