5 dicas e um bônus para deixar seu código Kotlin melhor
Lissa Ferreira
Posted on November 21, 2021
Kotlinautas
Esse conteúdo é oferecido e distribuído pela comunidade Kotlinautas, uma comunidade brasileira que busca oferecer conteúdo gratuito sobre a linguagem Kotlin em um espaço plural.
Créditos
Esse artigo foi baseado principalmente nesses slides do Anton Arhipov.
O quê é Kotlin Ideomático?
Kotlin Ideomático é uma maneira de escrever Kotlin tentando seguir os melhores padrões e funcionalidades da linguagem. Buscando tornar o código mais legível e menor.
Há uma página oficial da documentação do Kotlin apenas para listar diversas formas ideomáticas de fazer coisas. Caso saiba um pouco de inglês, é interessante ler esse documento. Neste artigo vamos abordar apenas algumas formas ideomáticas de se usar Kotlin, mas nessa página há uma quantidade bem maior.
Criando funções sem classes
Muitas pessoas que migram do Java para o Kotlin, continuam com o costume de criar uma classe toda vez que precisarem criar uma ou mais funções, mas isso não é necessário no Kotlin, pois podemos criar funções sem precisar de uma classe associada, dessa maneira:
fun main(){
olaMundo()
}
fun olaMundo(){
println("Olá Mundo!")
}
- Criamos uma função
olaMundo
, que mostra o textoOlá Mundo!
na tela; - Chamamos essa função dentro da
main
;
Extensões
Sabe aquelas funções .toInt
, .equals
,etc. que podemos usar em tipos do Kotlin? Podemos adicionar novas funções completamente feitas por nós á esses tipos, usando as extensões.
Vamos supor que você quer criar uma função chamada ÉNumero
que irá checar se uma string é um número ou não. Essa função seria executada da seguinte forma:
"isso não é um número".ÉNumero
"10".ÉNumero
Isso pode ser feito criando a função ÉNumero
dessa maneira:
fun String.ÉNumero() = all { it.isDigit() }
- Passamos o tipo, no caso
String
, seguido de um.
e o nome da função, que no caso éÉNumero
; - A função
all
irá testar se todos os caracteres do texto conseguem passar de uma certa condição, que no caso é se esse caractere é um dígito usando a funçãoisDigit
;
Após isso, podemos utilizar essa função em qualquer lugar do nosso código:
fun main(){
println("10".ÉNumero())
println("abracadabra".ÉNumero())
}
Funções de escopo
Funções de escopo são funções axuliares que executam um código com o contexto de um objeto. Isso significa que essas funções criam um escopo temporário, onde poderemos usar todas as propriedades de um objeto sem precisar informar esse projeto. Caso tenha tido alguma confusão, vamos ver na prática.
Vamos supor que temos uma classe Estrela
, com as propriedades nome
, diâmetro
, dessa maneira:
data class Estrela(
var nome: String = "",
var diâmetro: Int = 0,
var numeroDePlanetas: Int = 0,
)
Podemos criar uma variável que guarde uma instância, e mudar as propriedades dessa variável. Dessa maneira:
val sol = Estrela()
sol.nome = "sol"
sol.diâmetro = 1392700
sol.numeroDePlanetas = 8
Esse código irá funcionar, mas não está sendo ideomático, pois estamos repetindo a variável sol
diversas vezes. Podemos escrever esse código de uma maneira mais bonita como no exemplo abaixo:
val sol = Estrela().apply {
nome = "sol"
diâmetro = 1392700
numeroDePlanetas = 8
}
- Usamos a função
apply
do Kotlin, que irá receber um objeto (no caso uma instância deEstrela
) e irá fazer alterações com esse objeto em seu contexto. No caso, definindo valores de propriedades.
Dessa maneira, nosso código estará mais consiso, legível, e ideomático.
Há outras funções de escopo, essas outras funções podem ser vistas Nessa página da documentação do Kotlin
Argumentos Padrão e Argumentos Nomeados
Vamos supor que temos a seguinte função:
fun saudações(nome: String, momento: String){
println("Olá $nome! $momento")
}
Essa função está recebendo um nome
, como Pedro
ou Maria
, e momento recebe uma saudação do dia, como boa tarde
ou boa noite
.
Mas vamos pensar: Na maior parte das vezes, damos bom dia
para as pessoas, e menos vezes damos boa tarde
ou boa noite
.
Logo, podemos mudar a função e fazer que esse momento
tenha um valor padrão usando um =
depois de seu tipo.
fun saudações(nome: String, momento: String = "Bom Dia!"){
println("Olá $nome! $momento")
}
E além, e se essa pessoa não quiser passar seu nome? Podemos deixar Pessoa Anônima
como valor padrão, da mesma forma que dizemos com momento
. Dessa maneira:
fun saudações(nome: String = "Pessoa Anônima", momento: String = "Bom Dia!"){
println("Olá $nome! $momento")
}
Com isso, podemos chamar essa função saudações
de algumas formas:
fun main(){
saudações()
saudações("Maria")
saudações("Pedro", "Boa Noite!")
}
Resultado:
Olá Pessoa Anônima! Bom Dia!
Olá Maria! Bom Dia!
Olá Pedro! Boa Noite!
E se eu quiser deixar o argumento
nome
padrão, e mudar só a mensagem?
Isso pode ser feito nomeando o argumento momento
na chamada, dessa maneira:
fun main(){
saudações(momento = "Boa Tarde!")
}
Resultado:
Olá Pessoa Anônima! Boa Tarde!
Funções de única expressão
Vamos supor que temos uma função testarTemperatura
que recebe uma temperatura em String e diz se é possível tomar uma bebida nessa temperatura ou não:
fun testarTemperatura(temperatura: String): String{
when(temperatura){
"quente" -> return "Quente demais para beber"
"frio" -> return "Temperatura boa para beber"
else -> return "Preciso deixar um pouco na geladeira"
}
}
Essa função tem apenas uma única expressão, um único comando em seu corpo. logo, podemos simplificar essa função, removendo seu corpo e seu retorno e adicionando um =
seguido pela expressão.
Dessa maneira, nossa função ficará assim:
fun testarTemperatura(temperatura: String) = when(temperatura){
"quente" -> "Quente demais para beber"
"frio" -> "Temperatura boa para beber"
else -> "Preciso deixar um pouco na geladeira"
}
Dessa maneira, nossa função ficará bem menor, consisa e legível, essas são as funções de única expressão, a mesma coisa que fizemos com o when
pode ser feita com if
, try
,etc.
Operador Elvis
Vamos supor que temos uma classe Cachorro
, essa toda instância de Cachorro
tem um nome, raça (que pode ser null
caso esse cachorro seja vira-lata) e uma propriedade educado
. Dessa maneira:
class Cachorro(
val nome: String,
val raça: String?,
val educado: Boolean,
)
Junto com essa classe, temos uma função apresentarCachorro
que irá receber uma instância dessa classe Cachorro
, e caso esse cachorro seja de raça, e a sua raça não seja null
, o seu nome e raça serão mostrados na tela jutn ocom uma mensagem. Normalmente, fariamos dessa maneira:
fun apresentarCachorro(cachorro: Cachorro){
if (cachorro.raça == null){
return
}
val raça = cachorro.raça
val nome = cachorro.nome
if (cachorro.educado){
println("Au Au Au, meu nome é $nome e sou da raça $raça, Au Au Au")
}
}
Esse código pode ser melhorado. Podemos remover o primeiro if que testa se a raça do cachorro é null ou não. Podemos colocar esse teste direto na definição da variável raça
, dessa maneira:
fun apresentarCachorro(cachorro: Cachorro){
val raça = cachorro.raça ?: return
val nome = cachorro.nome
if (cachorro.educado){
println("Au Au Au, meu nome é $nome e sou da raça $raça, Au Au Au")
}
}
No código acima, usamos o operador Elvis (?:
), onde se o valor da esquerda for null
, o código da direita será executado. No caso, é o return
que irá fechar a função sem nenhum conteúdo no retorno.
Finalização
Nesse artigo, você aprendeu 6 dicas de como deixar o seu código Kotlin mais ideomático, consiso e legível. Busque aplicar os conceitos mostrados nesse artigo (e em outros sobre Kotlin Ideomático que podem existir) em seus projetos, pois assim seu código ficará bem melhor.
Muito obrigada por ler ❤️🏳️⚧️ e me segue nas redes, é tudo @lissatransborda 👀
Posted on November 21, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.