Curso Kotlin | #16. Funciones
Tags: kotlin, tutorial, spanish
Published: 2022-12-15 13:12:44

Bienvenido/a a otro capítulo del Curso de Kotlin! Podés consultar el curso completo desde [este link](https://github.com/maxwellnewage/kotlin-course) que te dejo acá. Podés seguirme por [LinkedIn](https://www.linkedin.com/in/maximilianoburgos/) o [Twitter](https://twitter.com/maxwellnewage) si querés estar al tanto de las próximas publicaciones.

Las funciones son procedimientos que se pueden reutilizar y nos permiten encapsular comportamientos y mejorar la lectura del código.

## Estructura
En todos nuestros ejemplos anteriores, escribimos el código en la función main:

```kotlin
fun main(args: Array<String>) {
```

Analicemos la estructura, señalando cada parte de la misma:

```kotlin
fun nombre(parametros: Tipo){
    // cuerpo
}
```

Toda función debe iniciar con la palabra reservada fun y luego continuar con su nombre. Entre paréntesis puede ir uno o más parámetros, pero también puede no tenerlos. Cada parámetro debe tener su tipo declarado; y dentro de las llaves (al igual que pasaba con la sentencia If) tendremos el cuerpo de la función, su comportamiento.

Nuestra función main contiene un Array de Strings porque nos permite decirle a Intellij que enviaremos parámetros por consola a la hora de ejecutar la aplicación. Ten esto en cuenta, pero no profundicemos todavía, dado que va a confundirte el uso particular de esta función.

## Nuestra primer función
¿Recuerdas el ejemplo de la clase anterior?:

```kotlin
print("Cual es tu nombre? >")
val name = readLine()
 
if(name.isNullOrEmpty()){
    throw Exception("El nombre no puede estar vacío!")
} else {
    print("Hola $name!")
}
```

Ahora imagina que quiero utilizar dos veces este algoritmo: quiero preguntar dos nombres e imprimirlos en pantalla si todo salió bien. Vamos a crear una función (fuera de main) y encapsular todo el contenido del ejemplo anterior:

```kotlin
fun sayMyName() {
    print("Cual es tu nombre? >")
    val name = readLine()
 
    if(name.isNullOrEmpty()){
        throw Exception("El nombre no puede estar vacío!")
    } else {
        print("Hola $name!")
    }
}
```

Una vez declarada la función, veremos que el texto se vuelve gris. Esto significa que no se está llamando en ningún lado, por lo cual lo vamos a solucionar en la función main:

```kotlin
fun main(args: Array<String>) {
    sayMyName()
    sayMyName()
}
```

La llamamos dos veces porque queremos preguntar por dos nombres. Nuestra función cumple su utilidad, pero vamos a volverla más flexible.

## Es hora de usar parámetros
Los parámetros en una función nos van a permitir obtener distintos resultados en base a la información que enviemos. Vamos a pasar el nombre por parámetro:

```kotlin
fun sayMyName(name: String?) {
```

Recuerda que el tipo tiene que ser String nullable porque vamos a enviarle el resultado de readLine.

```kotlin
fun main(args: Array<String>) {
    print("Cual es tu nombre? >")
    val name = readLine()
 
    sayMyName(name)
}
 
fun sayMyName(name: String?) {
    if(name.isNullOrEmpty()){
        throw Exception("El nombre no puede estar vacío!")
    } else {
        print("Hola $name!")
    }
}
```

Nos conviene que la función sayMyName no contenga código del input, porque ahora podemos usarla para cualquier tipo de entrada. Por ejemplo podríamos llevarnos esa función a un botón que la dispare en el momento de presionarlo, leyendo un campo de texto, como en un formulario.

## Retorno de una función
Una función que imprima nuestro nombre en pantalla esta bien, pero ¿qué ocurre si quiero guardar el resultado en una variable y utilizarla en otro lugar?. Necesitamos que nuestra función retorne la misma:

```kotlin
fun sayMyName(name: String?): String {
```

Al escribir “: Tipo” luego de los paréntesis de nuestra función, declaramos el retorno de la misma. Anteriormente no necesitábamos esto porque nuestra función no tenía retorno (el famoso void de Java), pero ahora requerimos devolver un String:

```kotlin
fun sayMyName(name: String?): String {
    if(name.isNullOrEmpty()){
        throw Exception("El nombre no puede estar vacío!")
    }
     
    return "Hola $name!"
}
```

He removido el else del condicional para limpiar un poco el código, pero el resultado es el mismo. Quité el print y lo convertí en un “return [string]”. Si ejecutamos el programa ahora mismo, no nos devolverá nada porque tenemos una función que devuelve un valor, el cual no se esta guardando ni tampoco imprimiendo. Vamos a arreglar eso:

```kotlin
val output = sayMyName(name)
println(output)
```

Podemos simplificar todo en una linea si no queremos reutilizar la salida:

```kotlin
println(sayMyName(name))
```

## Valor por Defecto
Kotlin nos permite definir valores por defecto en una función. Esto en Java no existía y teníamos que simularlo a través de la sobreescritura de métodos, algo que veremos mucho más adelante.

Vamos a definir un valor para name cuando no se ingrese nada en consola:

```kotlin
fun sayMyName(name: String? = "Maxwell"): String {
```

Esto nos permite llamar a la función sin enviar un parámetro:

```kotlin
println(sayMyName())
```

Esto nos va a devolver “Hola Maxwell!”. No existe un límite en la cantidad de parámetros por defecto que queramos agregar.

## Funciones Inline
Si el cuerpo de la función solo posee una linea, podemos utilizar funciones inline. Por ejemplo, implementemos una funcion que sume dos números y los retorne:

```kotlin
fun sum(num1: Int, num2: Int): Int {
    return num1 + num2
}
```

Por supuesto no hay nada mal en esta función, pero podemos implementarla como una inline function:

```kotlin
fun sum(num1: Int, num2: Int): Int = num1 + num2
```

Como habrán notado, se quita el return porque al escribir el signo de igualdad, Kotlin infiere que se trata de una inline function y lo que siga después es parte de su retorno. Esta forma se utiliza muchísimo, especialmente cuando entremos en el terreno de la programación orientada a objetos.

## Conclusiones
Las funciones nos acompañarán a lo largo de todo el resto de la serie del curso de Kotlin. Es fundamental comprender su funcionamiento e implementación dado que nos darán una flexibilidad mayor en las próximas entregas.