DEV Community

Cover image for Aprendizado Kotlin - Alguns recursos da linguagem
Antonio Lazaro for CollabCode

Posted on

5 2

Aprendizado Kotlin - Alguns recursos da linguagem

Originalmente publicado no blog do autor.

Introdução

Durante o curso de Kevin Jones "Getting Started with Kotlin" da Plural Sight tive oportunidade de conhecer alguns conceitos de Kotlin que achei bastante interessante e resolver compartilhar.

No próprio site da linguagem, existem vários tutoriais e recomendações de livros, alem do próprio Getting Started do site que fala de diversas características e recursos da linguagem e ferramentas associadas. Achei também o guia de referência da linguagem muito rico e completo.

Para quem se interessa pela estrutura da linguagem, existe disponível também a gramática da linguagem.

Recursos da linguagens observadores e experimentados

Nessa seção, pretendo falar de alguns recursos que pude experimentar durante o curso, e pratiquei em um projeto piloto que está disponível em um repositório no meu github onde pretendo colocar os demos do que ando testando com Kotlin. Esse repositório é o kotlin-lab.

Declaração de variáveis e propriedades: val x var - Suporte a imutabilidade de objetos nativamente

Em kotlin para declarar uma variável é possível a seguinte estrutura

[propertyType] =

A estrutura acima é explicada da seguinte forma:

  • val = Variável é imutável. Uma vez atribuído um valor, a referência não pode mais mudar. Se houver essa tentativa de atribuição, o compilador acusa erro.
  • var = Variável mutável. Comum como qualquer variável.
  • propertyName = nome da variável ou propriedade.
  • propertyType = atributo opcional. Caso não seja declarado, será colocado por inferência pela atribuição da primeira referência. Uma vez atribuido, esse tipo não pode receber outro tipo. A linguagem Kotlin não é dinamicamente tipada como JavaScript.
  • propertyValue = Valor atribuído da variável.
val teste: String;
teste = "Teste";
teste = "Teste 2"; //erro de compilação por fazer uma reatribuição
teste = 10; //erro de compilação por atribuir outro tipo
val inteiro; //erro de compilação. Não é possível fazer inferência sem atribuição e sem definir o tipo

Uso de constantes

Para declaração de constantes existe a palavra reserva const. Exemplo:

const val x = 2

Tipos primitivos

Os tipos primitivos de Kotlin são objetos.



Tipos primitivos inteiros e suas faixas de valores:



Tipos primitivos booleanos e de ponto fluante e suas faixas de valores.:

Strings

Strings são literais definidos entre "". Em Kotlin ela é uma sequencia imutável de códigos UTF-16.

String templates

Em Kotlin, é possível trabalhar com String Templates, como no JavScript, onde variáveis podem ser acessadas através do caracter \$, evitando assim a necessidade de concatenação de Strings. Caso seja necessário usar o caracter \$, deve ser feito o uso do escape: \\$

Exemplo:

val name = "Anne"
val yearOfBirth = 1985
val yearNow = 2018
val message = "$name is ${yearNow - yearOfBirth} years old"

Condicionais (if/else)

A condição fica entre parenteses () e o corpo da condição deve ser envolvido por chaves {}. A condição deve ter retorno booleano.

val age = 42
if (age < 10) {
println("You're too young to watch this movie")
} else if (age < 13) {
println("You can watch this movie with a parent")
} else {
println("You can watch this movie")
}

Como em outras linguagens de programação, o uso da condicional sem as chaves envolve o risco de alguma condição não ser devidamente executada, por isso, é extremamente recomendado se trabalhar com essa sinalização explicitamente.

if (age < 10)
println("You're too young to watch this movie")
println("You should go home") // Erro de lógica, esse trecho de código sempre será executado, independente da condicional.

O if/else é também uma expressão, o que pode funcionar como um operador ternário em Java. Quando se usa essa condição, é obrigatório definir um regra para o bloco else.

val result = if (condition) trueBody else falseBody

Comparações

Estrutura de comparação são feitas sempre com == ou !=. Quando invocados esses símbolos, eles automaticamente invocam o equals da classe em questão.

Comparações são chamadas de equalidade estrutural e o compilador traduz a == b, conforme exemplo abaixo:

a?.equals(b) ?: (b === null)

Para comparação de referência, deve ser utilizado os operadores === ou !==.

When

Esse operador seria equivalente ao Switch do Java, só que é um switch/case muito mais robusto.

Alguns exemplos de uso:

when (x) {
1 -> print("x == 1")
2 -> print("x == 2")
else -> { // Note the block
print("x is neither 1 nor 2")
}
}

Combinando diversos valores para mesma condição:

when (x) {
0, 1 -> print("x == 0 or x == 1")
else -> print("otherwise")
}

Pode ser usada expressões como condição:

when (x) {
parseInt(s) -> print("s encodes x")
else -> print("s does not encode x")
}

E tem suporte a negação através do caracter ! e a range (intervalos), bem como coleções.

when (x) {
in 1..10 -> print("x is in the range")
in validNumbers -> print("x is valid")
!in 10..20 -> print("x is outside the range")
else -> print("none of the above")
}

Estruturas de repetição

for

For faz iteração através de qualquer coisa que provenha um iterator. Similar ao que temos de foreach do Java.

for (item in collection) print(item) // exemplo 1
//ou
for (item: Int in ints) { // exemplo 2
// ...
}
for (i in array.indices) { //iterando um array ou uma lista indexada
println(array[i])
}
for (i in 1..3) { //interando um range de números
println(i)
}
for (i in 6 downTo 0 step 2) { //iterando uma contagem regressiva, definindo o salto
println(i)
}
for (x in 0 until 10 step 2) println(x) // Prints 0, 2, 4, 6, 8

// Iterate over the entries as objects that contain the key and the value as properties
for (entry in map) {
println("${entry.key}: ${entry.value}")
}
// Iterate over the entries as separate key and value objects
for ((key, value) in map) {
println("$key: $value")
}

// Iterate over the keys
for (key in map.keys) {
println(key)
}

// Iterate over the values
for (value in map.values) {
println(value)
}

while/do-while

Não tem muita mudança em relação a outras linguagens.

while (x > 0) {
x--
}

do {
val y = retrieveData()
} while (y != null) // y is visible here!

Collections

A classe Array é equivalente ao array[] do Java. Esse tipo de lista tem um tamanho fixo. As principais estruturas de dados do Java existem em Kotlin. Além do Array, temos o List, Set (dados não se repetem baseado na regra do equals) e Map (chave/valor). O map equivale ao dicionário (dict) do Python.

Exemplo de como criar collections em Kotlin:

val strings = listOf("Anne", "Karen", "Peter") // List<String>
val map = mapOf("a" to 1, "b" to 2, "c" to 3) // Map<String, Int>
val set = setOf("a", "b", "c") // Set<String>

A sintaxe acima cria listas imutáveis. Não pode ser modificado nem o tamanho, nem seus elementos. Para criação de listas mutáveis, existem outros métodos:

val strings = mutableListOf("Anne", "Karen", "Peter")
val map = mutableMapOf("a" to 1, "b" to 2, "c" to 3)
val set = mutableSetOf("a", "b", "c")

Para criar coleções vazias, é necessário definir o tipo ou colocar a tipificação no método de criação. Como na sintaxe abaixo:

val noInts: List<Int> = listOf()
val noStrings = listOf<String>()
val emptyMap = mapOf<String, Int>()

Hierarquia de interfaces em Kotlin segue conforme figura abaixo:

De maneira resumida:

  • Collection é usada quando podemos trabalhar tanto com List quanto com Set. = MutableCollection é Collection com operações de escrita add/remove.
  • List é usado preservando a ordem e podendo ser acessado por índice. Os índices iniciam em zero e o último elemento é list.size-1. A lista suporta elementos null, inclusive que podem se repetir. Duas listas são consideradas iguais se elas tem o mesmo tamanho e os elementos são iguais e estão na mesma posição. Implementação default é ArrayList.
  • MutableList: É uma lista com operação de escritas add/remove (existem outros métodos)
  • List x Array: Eles são muito similares entretanto, um array tem seu tamanho definido na sua inicialização e nunca mudará. Uma lista ela não tem um tamanho pré-definido, e pode mudar de tamanho a partir de operações de escrita.
  • Set: Armazena elementos únicos (exclusivos). A ordem normalmente não é um critério relevante. Pode armazenar, um e apenas um valor null. Duas coleções desse tipo são iguais se tem o mesmo tamanho e possuem os mesmos elementos. Implementação default é LinkedHashSet que preserva ordem de inseração, porém existe HashSet que a ordem não é relevante e consequentemente é mais performática que a estrutura default;
  • MutableSet: Set com operações de escrita.
  • Map: Estrutura com chave/valor. Lembra um cache ou uma tabela de banco de dados. As chaves são unicas e os valores podem ser repetidos se as chaves forem diferentes. Dois maps são iguais se possuem se suas chaves/valores são iguais. A implementação default é LinkedHashMap que preserva a ordem de inserção. Como alternativa tem o HashMap que não guardar a ordem de inseração e se baseaia no código hash, como no HashSet.
  • MutableMap: É um map com operação de escrita.

Um recurso bastante interessante em Kotlin é que você pode utilizar operadores + e - para coleções.

val numbers = listOf("one", "two", "three", "four")
val plusList = numbers + "five"
val minusList = numbers - listOf("three", "four")
println(plusList)
println(minusList)

Conclusão

Nesse estudo, comparei com Java as estruturas básicas de programação com Kotlin. Nos próximos, pretendo trazer outros recursos que a linguagem oferece.



Conheça a série sobre Kotlin

Outras Fontes:

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay