DEV Community

Cover image for Introdução ao Kotlin
Ronaldo Costa de Freitas
Ronaldo Costa de Freitas

Posted on • Updated on

Introdução ao Kotlin

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 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:

Em Kotlin:

É 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:

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)
Enter fullscreen mode Exit fullscreen mode

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:

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:

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

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:

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:

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:


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:

Próximo post:

Top comments (0)