Argumentos nomeados e opcionais no Kotlin
Tags: kotlin
Published: 2023-05-31 15:54:46

Um dos recursos que mais gosto do Kotlin são os [argumentos nomeados](https://kotlinlang.org/docs/functions.html#named-arguments) (named arguments) seguido dos [argumentos padrões](https://kotlinlang.org/docs/functions.html#default-arguments) (default arguments), a partir deles, temos uma maior flexibilidade no nosso código, seja na implementação ou reutilização de uma classe ou função.

E para demonstração vamos começar com uma classe que representa um usuário:

```kotlin
class User(
    val firstName: String,
    val lastName: String,
    val age: Int,
    val bio: String,
    val site: String?,
    val address: Address?
)
```

Então, vamos considerar a criação de um objeto para representar o usuário:

```kotlin
val alex = User(
    "Alex",
    "Felipe",
    28,
    "Instrutor na Alura",
    null,
    null
)
```

Observe que essa amostra precisa apenas do nome, sobrenome, idade e biografia, mas, mesmo assim, tivemos que enviar valores nulos dado que não indicamos um site ou endereço e isso poderia acontecer para qualquer propriedade que não é necessária!

## Utilizando argumentos padrões

Para melhorar a experiência de escrita do código, podemos considerar o seguinte: em parâmetros que podem ser nulos ou opcionais, utilizamos os argumentos padrões!

```kotlin
class User(
    val firstName: String,
    val lastName: String,
    val age: Int,
    val bio: String = "",
    val site: String? = null,
    val address: Address? = null
)
```

Apenas com esse ajuste, podemos criar um usuário apenas com nome, sobrenome e idade:

```kotlin
val alex = User(
    "Alex",
    "Felipe",
    28
)
```

Veja que agora, conseguimos flexibilizar o uso da classe que representa o usuário!

## Problemas ao adicionar novos parâmetros

Entretanto, apenas argumentos padrões não é o suficiente para que a instância não evit problemas com mudanças futuras, como por exemplo, se adicionarmos um campo novo para definir um id opcional:

```kotlin
class User(
    val id: Long = 0L,
    val firstName: String,
    val lastName: String,
    val age: Int,
    val bio: String = "",
    val site: String? = null,
    val address: Address? = null
)
```

Com apenas essa pequena alteração, precisamos modificar qualquer criação de usuário que não define um `id` dentro do nosso código.

## Utilizando argumentos nomeados 

Para flexibilizar a mudança de parâmetros nos construtores da classe ou funções, utilizamos os argumentos nomeados:

```kotlin
val alex = User(
    firstName = "Alex",
    lastName = "Felipe",
    age = 28
)
```

Pronto! Apenas com essa abordagem, podemos modificar a nossa classe ou função, adicionando novos parâmetros com argumentos padrões, que não haverá a necessidade de modificações das chamadas dentro do código.

Também, os argumentos nomeados podem ser enviados em qualquer ordem:

```kotlin
val alex = User(
    age = 28,
    lastName = "Felipe",
    firstName = "Alex"
)
```

## Mais exemplos

Um caso de uso bastante comum são em implementações de Composables, observe a implementação do composable `Box`:

```kotlin
@Composable
inline fun Box(
    modifier: Modifier = Modifier,
    contentAlignment: Alignment = Alignment.TopStart,
    propagateMinConstraints: Boolean = false,
    content: @Composable BoxScope.() -> Unit
) {
    ...
}
```

Note que precisamos apenas enviar o argumento para `content` (geralmente um trailing lambda), e podemos usar argumentos nomeados para garantir a compatibilidade e por ai vai... Aqui vão algumas variações de chamada do `Box`:

```kotlin
Box {

}
Box(modifier = Modifier) {

}
Box(
    content = { },
    contentAlignment = Alignment.Center
)
```

Entenda que esse tipo de abordagem é bastante comum e usar sabiamente esses dois recursos vai garantir que você escreva um código mais consistente e com maiores facilidades de crescimento.

O que você achou desses recursos do Kotlin, já utilizava no seu dia a dia? Se sim compartilhe comigo aqui nos comentários 😄