Introdução ao Kotlin
Tags: kotlin, java, jetbrains, oop
Published: 2022-11-02 04:04:06

Kotlin tomou o lugar do Java como linguagem oficial do Android e diversas grandes empresas vem migrando seus back-ends de Java para Kotlin. Neste post vou mostrar a você porquê isso vem acontecendo.

## O poder do Kotlin

Kotlin é tão poderosa quanto o Java e isso é incrível. No post [anterior](https://dev.to/ronaldocoding/breve-historia-do-kotlin-4845) eu falei um pouco sobre a interoperabilidade entre as duas  e contei brevemente a história da linguagem criada pelos engenheiros da Jetbrains. Essa interoperabilidade, aliada ao quão concisa Kotlin é, a torna uma substituta perfeita para a mãe dos legados.

Vamos tomar como exemplo uma classe que representa uma conta corrente em Java e em Kotlin.

Em Java:
{% embed https://gist.github.com/ronaldocoding/61d7dd30b3d38adc2411a4b3889f919b %}

Em Kotlin:
{% embed https://gist.github.com/ronaldocoding/e934238b7047d09f887448e76be5f4fe %}

É isso mesmo, o código Kotlin acima faz exatamente o que o em Java faz 😱

A ideia da classe ContaCorrente é representar um conta com as seguintes propriedades: um titular, que pode ser mudado, um cpf, uma agência, uma conta, todos imutáveis e um saldo, mutável, é claro. Para construi essa classe em Java respeitando os princípios do encapsulamento, temos que desenvolver os getters e setters necessários, além de criar funções auxiliares como `toString()`, `copy()`, `equals()` e `hashCode()`. Mas para fazer isso em Kotlin basta criar uma data class, usar os declaradores de propriedades corretos (`var` e `val`) e pronto: temos todos os getters e setters necessários além das funções antes mencionadas!

Para verificarmos a veracidade disso, vamos analisar o código abaixo:

{% embed https://gist.github.com/ronaldocoding/6a3b944c3fa7a21bd578a89859eae56a %}

Nesse programa Kotlin nós instanciamos as duas classes que representam uma conta corrente e chamamos todos os seus métodos para compararmos seus poderes de abstração. Repare que para acessar os getters e setters em Kotlin, basta usarmos a notação de `.`. Eis a saída:

```
Ronaldo
João
022.521.260-94
69624
246964
10000.0
12000.0
ContaCorrenteKt(titular=João, cpf=70116672293, agencia=69624, conta=246964, saldo=12000.0)
152796811
false

Ronaldo
João
022.521.260-94
69624
246964
10000.0
12000.0
ContaCorrenteJava(titular=João, cpf=70116672293, agencia=69624, conta=246964, saldo=12000.0)
181425962
false

ContaCorrenteKt(titular=João, cpf=70116672293, agencia=69624, conta=246964, saldo=12000.0)
ContaCorrenteJava(titular=João, cpf=70116672293, agencia=69624, conta=246964, saldo=12000.0)
```

Como podemos ver, ambas tem o mesmo poder de abstração, mas a diferença de verbosidade entre as duas é gigante! E esse é um pequeno gostinho do porquê Kotlin é cada vez mais adotado quando comparada a Java.

## Var e Val

Você deve ter reparado que usamos diversas vezes duas palavras-chaves muito importantes em Kotlin: `var` e `val`. E o que elas significam? Basicamente, essa é a notação que a linguagem usa para declarar propriedades que são mutáveis e aquelas que são imutáveis.

Ao declarar uma propriedade como `var` (vem de _variable_), queremos dizer que ela é mutável e ganhamos de brinde os seus setter e getter de forma implícita, ela corresponde a uma variável em Java com seus métodos getter e setter.

Ao declarar uma propriedade como `val` (vem de value), queremos dizer que ela é imutável e, é claro, já temos seu método getter implementado implicitamente. Desse modo, ela corresponde a uma variável final em Java com seu getter já desenvolvido.

É importante salientar que apesar das propriedades já virem com seus getters e setters implementados, não significa que nós não podemos customizá-los. Vamos implementar uma nova propriedade na nossa classe de conta corrente e criar um getter customizado. Essa propriedade representa a resposta para a pergunta: “a conta está negativada?”, `true` para sim e `false` para não. Dessa forma basta que o getter dessa propriedade seja a comparação entre o saldo da conta e zero:

{% embed https://gist.github.com/ronaldocoding/4217c984e3242277067f70441734d1e9 %}

E pronto: já temos um getter customizado! Agora para fazer um setter customizado vamos implementar um setter para a propriedade saldo. A lógica é a seguinte: o saldo só será alterado se o valor passado para o setter for positivo:

{% embed https://gist.github.com/ronaldocoding/83968f6951eb02e7f9073bf41d965973 %}

Feito. Repare que antes de implementar o setter, tivemos que inicializar a propriedade, isso foi necessário pois o setter usa o valor da propriedade para fazer a atribuição, por isso ela não pode ser nula. E quanto a palavra-chave `field`, ela representa a própria propriedade, é algo parecido ao usar `this.saldo` em Java.

## Funções

Como já deve ter percebido, para se declarar uma função em Kotlin, usamos a palavra-chave `fun`, pra você ver como é divertido programar em Kotlin 🤣. Além disso a função chamada `main` é a função especial que indica onde o programa deve começar a ser executado. Agora vamos analisar de forma mais profunda a sintaxe das funções com um exemplo do _Kotlin in Action_:


![Sintaxe função em Kotlin](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hiexb63q335djs4ickc2.png)

Assim como em Java, o nome da função vem logo no início, nesse caso `max`, depois entre parênteses temos seus parâmetros na forma `<nome>: <Tipo>`, em seguida após os dois pontos o tipo de retorno da função e por fim, entre chaves, o seu corpo em si. Essa função compara dois valores e retorna o maior. Repare que em Kotlin o `if` não é uma declaração (_statement_), mas sim uma expressão, ou seja, ela tem um valor, que está atrelado às suas comparações lógicas. No caso acima, se `a` for maior que `b`, o valor da expressão será `a`, caso contrário será `b`, e é por isso que a expressão pode ser retornada.

Obs: existe outra forma mais concisa de escrever a função `max` em Kotlin:

{% embed https://gist.github.com/ronaldocoding/451affc43bc58a97fd640ed633af2f8a %}

O `=` substitui o tipo de retorno da função, as chaves e a palavra-chave `return`. Muito legal, né?

## Null safety

Para fechar com chave de ouro vamos falar sobre uma das melhores qualidades do Kotlin: sua segurança. Você, pessoa desenvolvedora Java, quantos vezes já não se deparou com o maldito `NullPointerException`? Pois saiba que com Kotlin seus problemas acabaram, ou quase isso.

Nessa tão querida linguagem, nós podemos declarar propriedades como nuláveis ou não-nuláveis (em português isso fica bem feio, mas em inglês é _nullable_ e _non-nullable_), da seguinte forma:

{% embed https://gist.github.com/ronaldocoding/afea787100a563d0fc0a81fd51634828 %}

Para acessar a propriedade `nome`, não temos nenhum problema, pois sabemos que ela não pode ser nula. Mas e quanto a propriedade `sobrenome? Em Java, seria necessário fazer o seguinte:

```
if(sobrenome != null) System.out.println(sobrenome.length());
```

Mas em Kotlin, nós temos uma feature muito útil chamada `safe call`. De modo que o código acima pode ser reduzido ao seguinte:

```
println(sobrenome?.length)
```

Trata-se da notação `?.`, ela garante que estamos acessando uma propriedade que não está nula no momento, do contrário retorna apenas null. Essa notação é muito útil em chamadas encadeadas como o seguinte exemplo de [kotlinlang.org](https://kotlinlang.org/docs/null-safety.html#safe-calls):

```
bob?.department?.head?.name = managersPool.getManager()
```

Se qualquer uma das propriedade da cadeia for nula, essa atribuição é pulada e não considerada.

Mas e para o caso de eu querer fazer uma atribuição de uma propriedade non-nullable para uma propriedade nullable? Você poderia fazer o seguinte:

```
val l: Int = if (b != null) b.length else -1
```

Porém veja que mais uma vez precisamos de uma expressão inteira para uma simples atribuição. Foi pensando em solucionar isso que Kotlin tem o brilhante Elvis operator!

```
val l: Int = b?.length ?: -1
```

Nome criativo, não? Esse operador `?:` serve para avaliar se a expressão à esquerda é nula, caso ela não seja, ele a retorna, caso seja, ele retorna o operador à direita!

Agora, se mesmo com todas essas opções você ainda quiser ver um `NullPointerException`, Kotlin deixa, basta usar o operador `!!`:

```
val l = b!!.length
```

Nesse caso, se `b` não for nulo, seu valor será retornado, mas caso seja, uma `NullPointerException` será lançada!

## Próximos posts

E por hoje é isso, pessoal! Conseguimos falar um pouco sobre Kotlin, mas faltam alguns conceitos importantes como as clássicas expressões `for`, `while`, uma expressão nova chamada `when`, entre outras que vamos discutir no próximo post sobre Kotlin.

Obrigado pela atenção, até a próxima!

Post anterior:

{% embed https://dev.to/ronaldocoding/breve-historia-do-kotlin-4845 %}

Próximo post:

{% embed https://dev.to/ronaldocoding/estruturas-de-controle-em-kotlin-3d2n %}