Kotlin, assim como outras linguagens de programação de alto nível, tem estruturas de controle básicas como while
, for
e if
. No post de hoje vamos conhecê-las e aprender sobre a estrutura substituta do switch
, o when
.
Estrutura while
Essa estrutura de controle é bem similar ao Java, sendo praticamente idêntica. Além de while
, também temos sua irmã, a estrutura do-while
. Como são muito parecidas com as em Java, vamos analisar brevemente dois códigos sobre elas.
A estrutura while
tem o seguinte formato:
fun main() {
var palavra = ""
while(palavra.length <= 10) {
palavra += 'z'
}
}
Ou seja, o programa irá executar repetidamente uma ou mais linhas de código enquanto uma condição for atendida. No caso acima, o loop irá ocorrer até que o tamanho da string seja menor ou igual a 10, o loop irá cessar quando a palavra alcançar o tamanho 11.
Por outro lado, a estrutura do-while
tem o seguinte formato:
fun main() {
var palavra = ""
do {
palavra += 'z'
} while(palavra.length != 0)
}
Enquanto na estrutura while
, não temos a garantia de que o loop será executado, na do-while
sabemos que ele ocorre ao menos uma vez. Como podemos ver acima, primeiro incrementamos a palavra em um caractere e depois comparamos se seu tamanho é diferente de zero, o que ocasiona em um loop infinito, visto que seu tamanho sempre será diferente de zero. No entanto, se usássemos while
, isso não teria ocorrido, já que a comparação teria sido feita antes do incremento.
Estrutura for
Diferentemente de while
e do-while
, a estrutura de controle for
em Kotlin é diferente da em Java e tem várias formas de uso específico, como iterar sobre um intervalo ou uma coleção.
Iterando sobre intervalos
Se quisermos imprimir todos os números naturais (incluindo o zero) até um certo outro número natural, excluindo ele mesmo, como podemos fazer em Kotlin? Podemos usar o operador ..
entre zero e o determinado número menos 1. Esse operador indica que estamos usando um intervalo entre dois valores:
import kotlin.random.Random
fun main() {
val numeroRandom = Random.nextInt(0, 100)
for(i in 0 .. numeroRandom-1) {
println(i)
}
}
No código acima, primeiro obtemos um número pseudo-randômico entre 0 e 100 e depois usamos for com o operador ..
pra indicar que iremos iterar sobre esse intervalo, além de utilizarmos o operador in
que garante que o valor de i
esteja no intervalo especificado. Podemos deixar esse código mais idiomático usando a função until
, que simula esse comportamento de 0 (intervalo) valor - 1
:
import kotlin.random.Random
fun main() {
val numeroRandom = Random.nextInt(0, 100)
for(i in 0 until numeroRandom) {
println(i)
}
}
Também podemos iterar sobre intervalos utilizando outros funções como downTo
e step
. Se queremos imprimir todos os número pares entre 100 e 0, podemos fazer o seguinte:
fun main() {
for(i in 100 downTo 0 step 2) {
println(i)
}
}
A função downTo
indica que o intervalo é de trás para frente e a função step
faz com que dois números sejam pulados a cada iteração, assim, imprimindo apenas os números pares. Essa função está presente em todos esses for
s que envolvem intervalo, quando não a utilizamos explicitamente ela tem o comportamento padrão de pular um número de cada vez, ou seja step 1
.
Iterando sobre coleções
Assim como em Java, também podemos iterar sobre coleções (estruturas de dados de alto nível) em Kotlin, fazendo um trabalho semelhante ao forEach()
. Vamos fazer um programa que adiciona os quadrados dos números de uma lista de inteiros em outra:
fun main() {
val numeros = listOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
val numerosQuadrados = mutableListOf<Int>()
for(numero in numeros)
numerosQuadrados.add(numero * numero)
println(numerosQuadrados)
}
Note que também usamos o operador in
para iterar sobre a lista, basicamente desempacotando cada número da lista em uma variável chamada numero
. Também podemos usar o in
para iterar sobre caracteres:
fun main() {
val palavra = "Palavra"
var palavraEmMaiusculas = ""
for(letra in palavra) {
palavraEmMaiusculas += letra.toUpperCase()
}
println(palavraEmMaiusculas)
}
No código acima, nós iteramos sobre uma string e adicionamos cada caractere dela como uma letra maiúscula em outra string.
Estrutura if
De forma semelhante a while
, a estrutura de controla if
é praticamente idêntica a sua equivalente em Java, o que muda aqui é, conforme estudamos no último post, em Kotlin if
não é um statement, mas sim uma expressão, ou seja, ela tem um retorno. Vamos analisar a função abaixo:
fun ePar(numero: Int): Boolean {
return if(numero % 2 == 0) {
true
} else {
false
}
}
O que fazemos aqui é retorna o resultado da expressão if
que compara se um número inteiro, quando divido por 2, deixa resto zero. Também podemos fazer uma estrutura if
aninhada em Kotlin, usando else if
:
fun compara(A: Int, B: Int): String {
return if(A > B) {
"$A é maior que $B"
} else if(A < B) {
"$A é menor que $B"
} else {
"$A e $B são iguais"
}
}
Estrutura when
A estrutura when
é uma substituta para o if
em alguns casos, ela funciona como um switch
em Java e assim como o if
ela pode ter ramificações e retornar valores. Vamos reescrever os dois últimos códigos usando when
:
fun eParWhen(numero: Int) =
when {
numero % 2 == 0 -> {
true
}
else -> false
}
fun comparaWhen(A: Int, B: Int) =
when {
A > B -> "$A é maior que $B"
A < B -> "$A é menor que $B"
else -> "$A e $B são iguais"
}
A estrutura when
é muito útil para se lidar com Enums
, vamos analisar um exemplo do Kotlin in Action. Primeiro vamos criar a enum Color
que irá representar cores no formato RGB:
enum class Color(
val red: Int, val green: Int, val blue: Int
) {
RED(255, 0, 0), ORANGE(255, 165, 0), YELLOW(255, 255, 0), GREEN(0, 255, 0),
BLUE(0, 0, 255), INDIGO(75, 0, 130), VIOLET(238, 130, 238), WHITE(255, 255, 255);
fun rgb() = (red * 256 + green) * 256 + blue
}
Como pode ver, além de constantes, uma enum em Kotlin pode ter propriedades e funções, em adição a isso esse exemplo também mostra o único caso de uso de ponto e vírgula em Kotlin: para separar as constantes de uma enum das suas funções.
As constantes que foram definidas representam certas cores para certos valores das três propriedades e a função rgb()
retorna a ordem dessa cor na gama de cores que podem ser representadas no formato RGB.
Por exemplo, se usarmos essa função para a cor BLUE
, veremos que ela é a cor de número 255, agora se usarmos para a cor WHITE
, podemos observar que ela é a cor de número 16777215, ou seja, a última cor, já que podem ser representadas pouco mais de 16 milhões de cores em RGB.
Agora vamos usar when
para facilitar a nossa vida: caso precisássemos fazer uma função que retorna a "temperatura” de um certa cor, como faríamos ser usar vários if
s? Simples:
fun obtemTemperaturaCor(color: Color) =
when(color) {
Color.RED, Color.ORANGE, Color.YELLOW -> "Quente"
Color.GREEN -> "Neutra"
Color.BLUE, Color.INDIGO, Color.INDIGO, Color.VIOLET, Color.WHITE -> "Fria"
}
Veja só que beleza: podemos até combinar múltiplos valores em uma única ramificação, não é incrível 🤩?
Sendo assim, podemos observar que a forma dessa estrutura é a seguinte:
when (valorOpcional) {
condicao1 -> {
// faz alguma coisa
}
condicao2 -> {
//faz outra coisa
}
else -> { // else opcional
// faz algo
}
}
Diferentemente do switch
, não somos obrigados a passar o valor que será comparado entre parênteses e nem escrever declarações break
ao fim de cada ramificação.
Próximos posts
Nos próximos posts vamos nos aprofundar no estudo de funções e estudar classes, objetos e interfaces. Obrigado pela atenção, até a próxima!
Post anterior:
Próximo post:
Top comments (0)