Treinamento do Kotlin para programadores 2: noções básicas do Kotlin

Este codelab faz parte do curso Treinamento do Kotlin para programadores. Você aproveitará mais o curso se fizer os codelabs em sequência. Dependendo do seu conhecimento, talvez você possa passar mais rápido por algumas seções. Este curso é destinado a programadores que conhecem uma linguagem orientada a objetos e querem aprender Kotlin.

Introdução

Neste codelab, você aprenderá os conceitos básicos da linguagem de programação Kotlin: tipos de dados, operadores, variáveis, estruturas de controle e variáveis anuláveis e não anuláveis. Este curso é destinado a programadores que conhecem uma linguagem orientada a objetos e querem aprender Kotlin.

Em vez de criar um único app de exemplo, as lições deste curso foram desenvolvidas para aumentar seu conhecimento, mas são semi-independentes umas das outras para que você possa ler as seções que já conhece. Para conectá-los, muitos dos exemplos usam um tema de aquário. Se você quiser ver a história completa do aquário, confira o curso Bootcamp de Kotlin para programadores na Udacity.

O que você já precisa saber

  • Como criar um projeto no IntelliJ IDEA
  • Como abrir e executar código em REPL (Read-Eval-Print Loop) do Kotlin no IntelliJ IDEA (Tools > Kotlin > Kotlin REPL)

O que você vai aprender

  • Como usar tipos de dados, operadores e variáveis do Kotlin
  • Como trabalhar com booleanos e condições
  • A diferença entre variáveis anuláveis e não anuláveis
  • Como matrizes, listas e loops funcionam no Kotlin

Atividades do laboratório

  • Trabalhar com o REPL Kotlin para aprender os conceitos básicos da linguagem

Nesta tarefa, você aprenderá sobre operadores e tipos na linguagem de programação Kotlin.

Etapa 1: explorar os operadores numéricos

  1. Abra o IntelliJ IDEA, se ele ainda não estiver aberto.
  2. Para abrir o REPL do Kotlin, selecione Tools > Kotlin > Kotlin REPL.

Assim como em outras linguagens, o Kotlin usa +, -, * e / para adição, subtração, horários e divisão. O Kotlin também é compatível com diferentes tipos de números, como Int, Long, Double e Float.

  1. Digite as seguintes expressões no REPL. Para ver o resultado, pressione Control+Enter (Command+Enter no Mac) após cada um deles.
1+1
⇒ res8: kotlin.Int = 2

53-3
⇒ res9: kotlin.Int = 50

50/10
⇒ res10: kotlin.Int = 5

1.0/2.0
⇒ res11: kotlin.Double = 0.5

2.0*3.5
⇒ res12: kotlin.Double = 7.0

Os resultados das operações mantêm os tipos de operandos, portanto 1/2 = 0, mas 1,0/2,0 = 0,5.

  1. Teste algumas expressões com diferentes combinações de números inteiros e decimais.
6*50
⇒ res13: kotlin.Int = 300

6.0*50.0
⇒ res14: kotlin.Double = 300.0

6.0*50
⇒ res15: kotlin.Double = 300.0
  1. Chame alguns métodos em números. O Kotlin mantém números como primitivos, mas permite que você chame métodos em números como se fossem objetos.
2.times(3)
⇒ res5: kotlin.Int = 6

3.5.plus(4)
⇒ res8: kotlin.Double = 7.5

2.4.div(2)
⇒ res9: kotlin.Double = 1.2

Etapa 2: praticar usando tipos

O Kotlin não converte implicitamente entre tipos de números. Portanto, não é possível atribuir um valor curto diretamente a uma variável longa ou um Byte a um Int. Isso ocorre porque a conversão de número implícito é uma fonte comum de erros em programas. Você pode atribuir valores de diferentes tipos a qualquer momento para transmitir.

  1. Para ver algumas das transmissões possíveis, defina uma variável do tipo Int no REPL.
val i: Int = 6
  1. Crie uma nova variável e insira o nome dela mostrado acima, seguido por .to.
val b1 = i.to

O IntelliJ IDEA exibe uma lista de possíveis conclusões. Esse preenchimento automático funciona para variáveis e objetos de qualquer tipo.

  1. Selecione toByte() na lista e exiba a variável.
val b1 = i.toByte()
println(b1)
⇒ 6
  1. Atribua um valor Byte a variáveis de tipos diferentes.
val b2: Byte = 1 // OK, literals are checked statically
println(b2)
⇒ 1

val i1: Int = b2
⇒ error: type mismatch: inferred type is Byte but Int was expected

val i2: String = b2
⇒ error: type mismatch: inferred type is Byte but String was expected

val i3: Double = b2
⇒ error: type mismatch: inferred type is Byte but Double was expected
  1. Tente transmitir as atividades que retornaram erros.
val i4: Int = b2.toInt() // OK!
println(i4)
⇒ 1

val i5: String = b2.toString()
println(i5)
⇒ 1

val i6: Double = b2.toDouble()
println(i6)
⇒ 1.0
  1. Para tornar as constantes numéricas longas mais legíveis, o Kotlin permite colocar sublinhados nos números, o que faz sentido para você. Tente inserir constantes numéricas diferentes.
val oneMillion = 1_000_000
val socialSecurityNumber = 999_99_9999L
val hexBytes = 0xFF_EC_DE_5E
val bytes = 0b11010010_01101001_10010100_10010010

Etapa 3: conheça o valor dos tipos de variável

O Kotlin é compatível com dois tipos de variáveis: alterável e imutável. Com val, você pode atribuir um valor uma vez. Se você tentar atribuir algo novamente, receberá um erro. Com var, você pode atribuir um valor e mudá-lo mais tarde no programa.

  1. Defina as variáveis usando val e var e atribua novos valores a elas.
var fish = 1
fish = 2
val aquarium = 1
aquarium = 2
⇒ error: val cannot be reassigned

Você pode atribuir um valor a fish e atribuir um novo valor a ela, porque ela é definida com var. A tentativa de atribuir um novo valor a aquarium gera um erro porque está definida com val.

O tipo armazenado em uma variável é inferido quando o compilador consegue descobrir o contexto. Se quiser, você poderá especificar explicitamente o tipo de uma variável usando os dois pontos.

  1. Defina algumas variáveis e especifique o tipo explicitamente.
var fish: Int = 12
var lakes: Double = 2.5

Depois que um tipo for atribuído por você ou pelo compilador, não será possível alterá-lo ou você receberá um erro.

Etapa 4: saber mais sobre strings

Strings em Kotlin funcionam como strings em qualquer outra linguagem de programação usando " para strings e ' para caracteres únicos, e você pode concatenar strings com o operador +. É possível criar modelos de string combinando-os com valores. O nome $variable é substituído pelo texto que representa o valor. Isso é chamado de interpolação de variáveis.

  1. Crie um modelo de string.
val numberOfFish = 5
val numberOfPlants = 12
"I have $numberOfFish fish" + " and $numberOfPlants plants"
⇒ res20: kotlin.String = I have 5 fish and 12 plants
  1. Crie um modelo de string com uma expressão. Como em outras linguagens, o valor pode ser o resultado de uma expressão. Use as chaves {} para definir a expressão.
"I have ${numberOfFish + numberOfPlants} fish and plants"
⇒ res21: kotlin.String = I have 17 fish and plants

Nesta tarefa, você aprenderá sobre booleanos e condições de verificação na linguagem de programação Kotlin. Assim como outras linguagens, o Kotlin tem operadores booleanos e booleanos, como menor, igual a, maior que e assim por diante (<, ==, >, !=, <=, >=).

  1. Escreva uma instrução if/else.
val numberOfFish = 50
val numberOfPlants = 23
if (numberOfFish > numberOfPlants) {
    println("Good ratio!") 
} else {
    println("Unhealthy ratio")
}
⇒ Good ratio!
  1. Tente usar um intervalo em uma instrução if. No Kotlin, a condição que você testa também pode usar intervalos.
val fish = 50
if (fish in 1..100) {
    println(fish)
}
⇒ 50
  1. Escreva um if com vários casos. Para condições mais complicadas, use lógica e && e lógica ou ||. Assim como em outras linguagens, use else if para ter vários casos.
if (numberOfFish == 0) {
    println("Empty tank")
} else if (numberOfFish < 40) {
    println("Got fish!")
} else {
    println("That's a lot of fish!")
}
⇒ That's a lot of fish!
  1. Tente uma instrução when. Há uma maneira mais agradável de escrever essa série de instruções if/else if/else em Kotlin, usando a instrução when, que é como a instrução switch em outras linguagens. As condições em uma instrução when também podem usar intervalos.
when (numberOfFish) {
    0  -> println("Empty tank")
    in 1..39 -> println("Got fish!")
    else -> println("That's a lot of fish!")
}
⇒ That's a lot of fish!

Nesta tarefa, você aprenderá sobre variáveis anuláveis e não anuláveis. Erros de programação relacionados a valores nulos têm sido a fonte de vários bugs. O Kotlin procura reduzir bugs introduzindo variáveis não anuláveis.

Etapa 1: saiba mais sobre a nulidade

Por padrão, as variáveis não podem ser null.

  1. Declare um Int e atribua null a ele.
var rocks: Int = null
⇒ error: null can not be a value of a non-null type Int
  1. Use o operador de ponto de interrogação, ?, após o tipo para indicar que uma variável pode ser nula. Declare um Int? e atribua null a ele.
var marbles: Int? = null

Quando você tem tipos de dados complexos, como uma lista:

  • Você pode permitir que os elementos da lista sejam nulos.
  • É possível permitir que a lista seja nula, mas, se não for nula, os elementos dela não poderão ser nulos.
  • Você pode permitir que a lista ou os elementos sejam nulos.

As listas e alguns outros tipos de dados complexos serão abordados em uma tarefa posterior.

Etapa 2: saber mais sobre o e ?:

É possível testar null com o operador ?, o que evita a dificuldade de escrever muitas instruções if/else.

  1. Escreva algum código para verificar se a variável fishFoodTreats não é null. Em seguida, diminua essa variável.
var fishFoodTreats = 6
if (fishFoodTreats != null) {
    fishFoodTreats = fishFoodTreats.dec()
}
  1. Agora veja a maneira Kotlin de criá-la, usando o operador ?.
var fishFoodTreats = 6
fishFoodTreats = fishFoodTreats?.dec()
  1. Também é possível encadear testes nulos com o operador ?:. Veja este exemplo:
fishFoodTreats = fishFoodTreats?.dec() ?: 0

É uma abreviação de "se fishFoodTreats não for null, diminua e use. Caso contrário, use o valor após ?:, que é 0. Se fishFoodTreats for null, a avaliação será interrompida, e o método dec() não será chamado.

Um ponto sobre ponteiros nulos

Se você gosta muito do NullPointerExceptions, o Kotlin permite mantê-los. O operador de declaração não nulo, !! (double-bang), converte qualquer valor para um tipo não nulo e gera uma exceção se o valor for null.

val len = s!!.length   // throws NullPointerException if s is null

Nesta tarefa, você aprenderá sobre matrizes e listas, além de aprender maneiras diferentes de criar repetições na linguagem de programação Kotlin.

Etapa 1: criar listas

As listas são um tipo fundamental do Kotlin e são parecidas com as de outras linguagens.

  1. Declare uma lista usando listOf e imprima-a. Não é possível alterar essa lista.
val school = listOf("mackerel", "trout", "halibut")
println(school)
⇒ [mackerel, trout, halibut]
  1. Declare uma lista que pode ser alterada usando mutableListOf. Remover um item
val myList = mutableListOf("tuna", "salmon", "shark")
myList.remove("shark")
⇒ res36: kotlin.Boolean = true

O método remove() retornará true quando o item transmitido for removido.

Etapa 2: criar matrizes

Assim como outras linguagens, o Kotlin tem matrizes. Ao contrário das listas no Kotlin, que têm versões mutáveis e imutáveis, não há uma versão mutável de uma Array. Depois de criar uma matriz, o tamanho é fixo. Não é possível adicionar nem remover elementos, exceto copiando para uma nova matriz.

As regras sobre o uso de val e var são as mesmas de matrizes e listas.

  1. Declare uma matriz de strings usando arrayOf. Use o utilitário de matriz java.util.Arrays.toString() para imprimi-la.
val school = arrayOf("shark", "salmon", "minnow")
println(java.util.Arrays.toString(school))
⇒ [shark, salmon, minnow]
  1. Uma matriz declarada com arrayOf não tem um tipo associado aos elementos, então você pode combinar os tipos. Isso é útil. Declare uma matriz com tipos diferentes.
val mix = arrayOf("fish", 2)
  1. Também é possível declarar matrizes com um tipo para todos os elementos. Declare uma matriz de números inteiros usando intArrayOf(). Há builders correspondentes, ou funções de instanciação, para matrizes de outros tipos.
val numbers = intArrayOf(1,2,3)
  1. Combine duas matrizes com o operador +.
val numbers = intArrayOf(1,2,3)
val numbers3 = intArrayOf(4,5,6)
val foo2 = numbers3 + numbers
println(foo2[5])
=> 3
  1. Teste combinações diferentes de matrizes e listas aninhadas. Como em outras linguagens, é possível aninhar matrizes e listas. Ou seja, ao colocar uma matriz em uma, você terá uma matriz, e não uma matriz simplificada do conteúdo das duas. Os elementos de uma matriz também podem ser listas, e os elementos de listas podem ser matrizes.
val numbers = intArrayOf(1, 2, 3)
val oceans = listOf("Atlantic", "Pacific")
val oddList = listOf(numbers, oceans, "salmon")
println(oddList)
⇒ [[I@89178b4, [Atlantic, Pacific], salmon]

O primeiro elemento, numbers, é um Array. Quando você não usa o utilitário de matriz para exibi-lo, o Kotlin imprime o endereço em vez do conteúdo da matriz.

  1. Um bom recurso do Kotlin é que você pode inicializar matrizes com código em vez de inicializá-las como 0. Veja este exemplo:
val array = Array (5) { it * 2 }
println(java.util.Arrays.toString(array))
⇒ [0, 2, 4, 6, 8]

O código de inicialização está entre as chaves, {}. No código, it refere-se ao índice da matriz, começando com 0.

Etapa 3: criar repetições

Agora que você tem listas e matrizes, percorrer os elementos funciona conforme o esperado.

  1. Crie uma matriz. Use uma repetição for para iterar a matriz e exibir os elementos.
val school = arrayOf("shark", "salmon", "minnow")
for (element in school) {
    print(element + " ")
}
⇒ shark salmon minnow
  1. No Kotlin, é possível percorrer os elementos e os índices ao mesmo tempo. Veja este exemplo:
for ((index, element) in school.withIndex()) {
    println("Item at $index is $element\n")
}
⇒ Item at 0 is shark
Item at 1 is salmon
Item at 2 is minnow
  1. Tente diferentes tamanhos e intervalos de etapas. É possível especificar intervalos de números ou caracteres em ordem alfabética. E, como em outros idiomas, você não precisa avançar em 1. É possível voltar atrás usando downTo.
for (i in 1..5) print(i)
⇒ 12345

for (i in 5 downTo 1) print(i)
⇒ 54321

for (i in 3..6 step 2) print(i)
⇒ 35

for (i in 'd'..'g') print (i)
⇒ defg
  1. Teste alguns loops. Assim como outras linguagens, o Kotlin tem loops while, do...while e operadores ++ e --. O Kotlin também tem repetições repeat.
var bubbles = 0
while (bubbles < 50) {
    bubbles++
}
println("$bubbles bubbles in the water\n")

do {
    bubbles--
} while (bubbles > 50)
println("$bubbles bubbles in the water\n")

repeat(2) {
     println("A fish is swimming")
}
⇒ 50 bubbles in the water
49 bubbles in the water
A fish is swimmingA fish is swimming

O Kotlin é muito semelhante a outras linguagens quando se trata de conceitos básicos como operadores, listas e repetições, mas há algumas diferenças importantes.

Os seguintes recursos podem ser diferentes em Kotlin e em outras linguagens:

  • Os tipos Kotlin não podem ser convertidos implicitamente. Use o Cast.
  • As variáveis declaradas com val só podem ser atribuídas uma vez.
  • As variáveis do Kotlin não são anuláveis por padrão. Use ? para tornar as variáveis anuláveis.
  • Com o Kotlin, é possível repetir o índice e os elementos de uma matriz ao mesmo tempo em uma repetição for.

Os seguintes builds de programação do Kotlin são semelhantes aos de outras linguagens:

  • As matrizes e listas podem ter um único tipo ou tipos mistos.
  • As matrizes e listas podem ser aninhadas.
  • É possível criar repetições com for, while, do/while e repeat.
  • A instrução when é a versão em Kotlin da instrução switch, mas when é mais flexível.

Documentação do Kotlin

Se quiser mais informações sobre qualquer assunto deste curso ou se tiver dificuldades, https://kotlinlang.org é seu melhor ponto de partida.

Tutoriais do Kotlin

O site https://try.kotlinlang.org (link em inglês) tem tutoriais elaborados chamados Kotlin Koans, um intérprete baseado na Web, e um conjunto completo de documentação de referência com exemplos.

Curso Udacity

Para ver o curso da Udacity sobre esse assunto, consulte Bootcamp de Kotlin para programadores (link em inglês).

IntelliJ IDEA

A documentação do IntelliJ IDEA (em inglês) pode ser encontrada no site da JetBrains.

Esta seção lista as possíveis atividades para os alunos que estão trabalhando neste codelab como parte de um curso ministrado por um instrutor. Cabe ao instrutor fazer o seguinte:

  • Se necessário, atribua o dever de casa.
  • Informe aos alunos como enviar o dever de casa.
  • Atribua nota aos trabalhos de casa.

Os professores podem usar essas sugestões o quanto quiserem, e eles devem se sentir à vontade para passar o dever de casa como achar adequado.

Se você estiver fazendo este codelab por conta própria, use essas atividades para testar seu conhecimento.

Responda a estas perguntas

Pergunta 1

Qual das seguintes afirmações declara uma lista inalterável de strings?

val school = arrayOf("shark", "salmon", "minnow")

var school = arrayOf("shark", "salmon", "minnow")

val school = listOf("shark", "salmon", "minnow")

val school = mutableListOf("shark", "salmon", "minnow")

Pergunta 2

Qual será a saída do código a seguir?
for (i in 3..8 step 2) print(i)

▢ 345678

▢ 468

▢ 38

▢ 357

Pergunta 3

Qual é a finalidade do ponto de interrogação desse código?
var rocks: Int? = 3

▢ O tipo da variável rocks não foi corrigido.

▢ A variável rocks pode ser definida como nula.

▢ A variável rocks não pode ser definida como nula.

▢ A variável rocks não pode ser inicializada imediatamente.

Vá para a próxima lição: 3. funções

Para ter uma visão geral do curso, incluindo links para outros codelabs, consulte "Bootcamp de Kotlin para programadores: bem-vindo ao curso."