Exercícios: noções básicas do Kotlin

1. Antes de começar

Agora que você já estudou os princípios básicos da programação em Kotlin, é hora de colocar em prática o que aprendeu.

Estes exercícios testam sua compreensão dos conceitos que você estudou. Eles são baseados em casos reais e você provavelmente já viu alguns deles.

Siga as instruções para encontrar uma solução para cada problema. Se tiver dificuldades, alguns dos exercícios têm dicas que podem ajudar. O código da solução está disponível no final, mas é altamente recomendável resolver os exercícios antes de ver as respostas.

Considere as soluções como uma das maneiras de resolver os problemas e fique à vontade para testar como quiser. Você pode resolver alguns dos exercícios de várias maneiras, além de usar nomes diferentes para as funções e variáveis.

Resolva os problemas no seu tempo. Há uma duração estimada para cada exercício, mas não tem problema se eles não forem suficientes para você. Recomendamos que você reserve o tempo que precisar para resolver cada problema com cuidado.

É recomendável usar o Playground Kotlin para resolver esses exercícios.

Pré-requisitos

O que é necessário

  • Um computador com acesso à Internet e um navegador da Web.

2. Mostrar mensagens

Conte aos seus amigos o que você aprendeu nesse programa de aprendizagem.

  • Você consegue escrever uma função main() que gere essas mensagens em quatro linhas separadas?
Use the val keyword when the value doesn't change. 
Use the var keyword when the value can change.
When you define a function, you define the parameters that can be passed to it. 
When you call a function, you pass arguments for the parameters.

3. Corrigir erros de compilação

Este programa gera para o usuário um aviso de que ele recebeu uma mensagem de bate-papo de um amigo.

fun main() { 
    println("New chat message from a friend'}
}
  1. Você consegue descobrir e corrigir a causa raiz dos erros de compilação nesse programa?
  2. O código usa os símbolos adequados para indicar o argumento de abertura e fechamento do argumento da string e da função?

Dica: você pode usar o Playground Kotlin para executar o código e ver os erros de compilação.

Após a correção dos erros, o programa será compilado sem erros e mostrará esta saída:

New chat message from a friend

4. Modelos de string

Este programa informa os usuários sobre a próxima promoção de um determinado item. Ele tem um modelo de string, que depende da variável discountPercentage para o desconto percentual e da variável item para o item à venda. No entanto, há erros de compilação no código.

fun main() {
    val discountPercentage: Int = 0
    val offer: String = ""
    val item = "Google Chromecast"
    discountPercentage = 20
    offer = "Sale - Up to $discountPercentage% discount on $item! Hurry up!"
    
    println(offer)
}
  1. Você consegue descobrir e corrigir a causa dos erros?
  2. Você consegue determinar a saída desse programa antes de executar o código no Playground Kotlin?

Dica: é possível atribuir novamente um valor a uma variável somente leitura?

Após a correção dos erros, o programa será compilado sem erros e mostrará esta saída:

Sale - Up to 20% discount on Google Chromecast! Hurry up!

5. Concatenação de strings

Este programa mostra o número total de pessoas em uma festa. Ele inclui adultos e crianças. A variável numberOfAdults contém o número de adultos na festa, e a variável numberOfKids contém o número de crianças.

fun main() {
    val numberOfAdults = "20"
    val numberOfKids = "30"
    val total = numberOfAdults + numberOfKids
    println("The total party size is: $total")
}

Etapa 1

  • Você consegue determinar a saída desse programa antes de executar o código no Playground Kotlin?

Depois de determinar a saída, execute o código no Playground Kotlin e verifique se ela corresponde à que foi mostrada.

Dica: o que acontece quando você usa o operador + em duas strings?

Etapa 2

O código funciona e mostra alguns resultados, mas não o número total de pessoas participando.

  • Você consegue encontrar e corrigir o problema no código para que ele gere este resultado?
The total party size is: 50

6. Como formatar mensagens

Este programa mostra o salário total que um funcionário recebe no mês. O salário total é dividido em duas partes: a variável baseSalary, que o funcionário recebe todos os meses, e a variável bonusAmount, que é um bônus adicional concedido ao funcionário.

fun main() {
    val baseSalary = 5000
    val bonusAmount = 1000
    val totalSalary = "$baseSalary + $bonusAmount"
    println("Congratulations for your bonus! You will receive a total of $totalSalary (additional bonus).")
}
  1. Você consegue descobrir a saída desse código antes de o executar no Playground Kotlin?
  2. Quando você executa o código no Playground Kotlin, ele gera a saída esperada?

7. Implementar operações matemáticas básicas

Neste exercício, você vai criar um programa que executa operações matemáticas básicas e mostra a resposta.

Etapa 1

A função main() contém um erro de compilação:

fun main() {
    val firstNumber = 10
    val secondNumber = 5
    
    println("$firstNumber + $secondNumber = $result")
}
  • Você pode corrigir o erro para que o programa mostre este resultado?
10 + 5 = 15

Etapa 2

O código funciona, mas a lógica para adicionar dois números está localizada na variável resultante, tornando o código menos flexível à reutilização. Em vez disso, é possível extrair a operação de adição para uma função add() para que o código seja reutilizável. Para fazer isso, atualize o código para que fique como o mostrado abaixo. O código agora introduz uma nova variável val chamada thirdNumber e mostra o resultado dessa nova variável com firstNumber.

fun main() {
    val firstNumber = 10
    val secondNumber = 5
    val thirdNumber = 8
    
    val result = add(firstNumber, secondNumber)
    val anotherResult = add(firstNumber, thirdNumber)

    println("$firstNumber + $secondNumber = $result")
    println("$firstNumber + $thirdNumber = $anotherResult")
}

// Define add() function below this line
  • Você pode definir a função add() para que o programa gere essa saída?
10 + 5 = 15
10 + 8 = 18

Etapa 3

Agora você tem uma função reutilizável para adicionar dois números.

  • É possível implementar a função subtract() da mesma forma que a função add()? Modifique a função main() também para usar a função subtract() para verificar se ela funciona como esperado.

Dica: pense na diferença entre adição, subtração e outras operações matemáticas. Comece a trabalhar no código da solução a partir disso.

8. Parâmetros padrão

O Gmail tem um recurso que envia uma notificação ao usuário sempre que uma tentativa de login é feita em um novo dispositivo.

Neste exercício, você vai criar um programa que mostra uma mensagem aos usuários com este modelo:

There's a new sign-in request on operatingSystem for your Google Account emailId.

É necessário implementar uma função que aceite parâmetros operatingSystem e emailId, construa e retorne a mensagem no formato fornecido.

Por exemplo, se a função foi chamada com "Chrome OS" para o operatingSystem e "sample@gmail.com" para o emailId, ela vai retornar esta string:

There's a new sign-in request on Chrome OS for your Google Account sample@gmail.com.

Etapa 1

  1. É possível implementar a função displayAlertMessage() nesse programa para que ele mostre o resultado abaixo?
fun main() {
    val operatingSystem = "Chrome OS"
    val emailId = "sample@gmail.com"

    println(displayAlertMessage(operatingSystem, emailId))
}

// Define your displayAlertMessage() below this line.
  1. Seu programa mostra este resultado?
There's a new sign-in request on Chrome OS for your Google Account sample@gmail.com.

Etapa 2

Muito bem! Você mostrou a mensagem. No entanto, em alguns casos, você vai perceber que não é possível determinar o sistema operacional do usuário. Nessas situações, é preciso especificar o nome do sistema operacional como Unknown OS. É possível otimizar ainda mais o código para que não seja necessário transmitir o argumento Unknown OS sempre que a função for chamada.

  1. Você consegue encontrar uma maneira de otimizar o código com essas informações para que ele gere a saída abaixo?
There's a new sign-in request on Unknown OS for your Google Account user_one@gmail.com.

There's a new sign-in request on Windows for your Google Account user_two@gmail.com. 

There's a new sign-in request on Mac OS for your Google Account user_three@gmail.com. 
  1. Para mostrar a mensagem acima, substitua a implementação da função main() por esta:
fun main() {
    val firstUserEmailId = "user_one@gmail.com"

    // The following line of code assumes that you named your parameter as emailId. 
    // If you named it differently, feel free to update the name.
    println(displayAlertMessage(emailId = firstUserEmailId))
    println()

    val secondUserOperatingSystem = "Windows"
    val secondUserEmailId = "user_two@gmail.com"

    println(displayAlertMessage(secondUserOperatingSystem, secondUserEmailId))
    println()

    val thirdUserOperatingSystem = "Mac OS"
    val thirdUserEmailId = "user_three@gmail.com"

    println(displayAlertMessage(thirdUserOperatingSystem, thirdUserEmailId))
    println()
}

9. Pedômetro

O pedômetro é um dispositivo eletrônico que conta o número de passos. Atualmente, quase todos os smartphones, smartwatches e equipamentos de ginástica vêm com pedômetros integrados. O app de saúde e fitness usa pedômetros integrados para calcular esse número. Essa função calcula o número de calorias que o usuário queima com base nos passos dados.

  • Você consegue renomear as funções, parâmetros de funções e variáveis neste programa com base nas práticas recomendadas?
fun main() {
    val Steps = 4000
    val caloriesBurned = PEDOMETERstepsTOcalories(Steps);
    println("Walking $Steps steps burns $caloriesBurned calories") 
}

fun PEDOMETERstepsTOcalories(NumberOFStepS: Int): Double {
    val CaloriesBURNEDforEachStep = 0.04
    val TotalCALORIESburned = NumberOFStepS * CaloriesBURNEDforEachStep
    return TotalCALORIESburned
}

10. Comparar dois números

Os smartphones modernos têm um recurso integrado que monitora o tempo de uso, ou seja, o tempo que você passa no smartphone por dia.

Neste exercício, você vai implementar uma função que compara o tempo em minutos gasto no smartphone no dia atual com o tempo gasto no dia anterior. A função aceita dois parâmetros inteiros e retorna um valor booleano.

O primeiro parâmetro contém o número de minutos que você gastou no dia atual e o segundo contém o número de minutos gastos no dia anterior. A função vai retornar um valor true se você tiver passado mais tempo no smartphone no dia atual em comparação com o dia anterior. Caso contrário, ela retorna um valor false.

Por exemplo, se você chamou a função com os argumentos nomeados abaixo:

  • timeSpentToday = 300 e timeSpentYesterday = 250, a função retorna um valor true.
  • timeSpentToday = 300 e timeSpentYesterday = 300, a função retorna um valor false.
  • timeSpentToday = 200 e timeSpentYesterday = 220, a função retorna um valor false.

Dica: o operador de comparação > retorna true se o valor antes do operador for maior que o valor após o operador. Caso contrário, ela retorna um valor false.

11. Mover o código duplicado para uma função

Este programa mostra a previsão do tempo para diferentes cidades. Ele inclui o nome da cidade, as temperaturas máximas e mínimas do dia e a chance de chuva.

fun main() {
    println("City: Ankara")
    println("Low temperature: 27, High temperature: 31")
    println("Chance of rain: 82%")
    println()

    println("City: Tokyo")
    println("Low temperature: 32, High temperature: 36")
    println("Chance of rain: 10%")
    println()
    
    println("City: Cape Town")
    println("Low temperature: 59, High temperature: 64")
    println("Chance of rain: 2%")
    println()
    
    println("City: Guatemala City")
    println("Low temperature: 50, High temperature: 55")
    println("Chance of rain: 7%")
    println()
}

Existem muitas semelhanças com o código que mostra o clima de cada cidade. Por exemplo, há frases que são repetidas várias vezes, como "City:" (cidade) e "Low temperature:" (temperatura baixa). Códigos semelhantes e repetidos apresentam risco de erros no programa. Em uma das cidades, você pode ter um erro de digitação ou esquecer um dos detalhes meteorológicos.

  1. É possível criar uma função que mostra os detalhes do clima para uma cidade a fim de reduzir a repetição na função main() e fazer o mesmo com as cidades restantes?
  2. É possível atualizar a função main(), chamar a função que você criou para cada cidade e transmitir os detalhes adequados do clima como argumentos?

12. Código da solução

A solução usa a função println() para mostrar as mensagens em cada linha.

fun main() {
    println("Use the val keyword when the value doesn't change.")
    println("Use the var keyword when the value can change.")
    println("When you define a function, you define the parameters that can be passed to it.")
    println("When you call a function, you pass arguments for the parameters.")
}

Corrigir erros de compilação

O código continha dois erros de compilação:

  1. A string precisa terminar com aspas duplas em vez de uma aspa simples.
  2. O argumento da função precisa terminar com um parêntese em vez de uma chave.
fun main() { 
    println("New chat message from a friend")
}

Modelos de string

Os erros de compilação são causados pela atribuição das variáveis somente leitura discountPercentage e offer a novos valores, o que não é permitido.

fun main() {
    val discountPercentage = 20
    val item = "Google Chromecast"
    val offer = "Sale  - Up to $discountPercentage% discount off $item! Hurry Up!"

    println(offer)
}

Como solução alternativa, declare o número inteiro discountPercentage e a string offer usando a palavra-chave var. No entanto, os valores são imutáveis no contexto do programa, então você pode usar a palavra-chave val.

Concatenação de strings

Etapa 1

O programa gera esta saída:

The total party size is: 2030 

Essa era uma pergunta difícil. Quando o operador + é usado em valores String, ele produz uma string concatenada. Os números inteiros são colocados entre aspas duplas e, portanto, são tratados como strings em vez de números inteiros. Esse é o motivo da saída mostrar 2030.

Etapa 2

Você pode remover as aspas duplas ao redor das variáveis numberOfAdults e numberOfKids para as converter em variáveis Int.

fun main() {
    val numberOfAdults = 20
    val numberOfKids = 30
    val total = numberOfAdults + numberOfKids
    println("The total party size is: $total")
}

Lembre-se de que o compilador Kotlin pode inferir o tipo de variáveis com base nos valores atribuídos a elas. Nesse caso, o compilador infere que as variáveis numberOfAdults e numberOfKids são tipos Int.

Como formatar mensagens

O programa gera esta saída:

Congratulations for your bonus! You will receive a total of 5000 + 1000 (additional bonus).

"$baseSalary + $bonusAmount" usa a sintaxe de expressões de modelo. Nas expressões de modelo, o código é avaliado e, em seguida, o resultado é concatenado em uma string.

No exercício, a variável $baseSalary é avaliada como um valor 5000, e a variável $bonusAmount é avaliada como um valor 1000. Em seguida, o resultado é concatenado para produzir "5000 + 1000" e é atribuído à variável result.

Implementar operações matemáticas básicas

Etapa 1

Defina uma variável result imutável com a palavra-chave val e atribua a ela o resultado da operação de adição:

fun main() {
    val firstNumber = 10
    val secondNumber = 5
    
    val result = firstNumber + secondNumber
    println("$firstNumber + $secondNumber = $result")
}

Etapa 2

  1. Crie uma função add() que aceite parâmetros firstNumber e secondNumber, ambos do tipo Int, e retorne um valor Int.
  2. Digite o código da operação de adição no corpo da função add() e use a palavra-chave return para retornar o resultado da operação.
fun add(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber + secondNumber
}

Etapa 3

  1. Defina uma função subtract() que aceite parâmetros firstNumber e secondNumber, ambos do tipo Int, e retorne um valor de Int.
  2. Digite o código da operação de subtração no corpo da função subtract() e use a palavra-chave return para retornar o resultado da operação.
fun subtract(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber - secondNumber
}
  1. Modifique a função main() para usar a nova função subtract(). Um exemplo de solução seria:
fun main() {
    val firstNumber = 10
    val secondNumber = 5
    val thirdNumber = 8
    
    val result = add(firstNumber, secondNumber)
    val anotherResult = subtract(firstNumber, thirdNumber)

    println("$firstNumber + $secondNumber = $result")
    println("$firstNumber - $thirdNumber = $anotherResult")
}

fun add(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber + secondNumber
}

fun subtract(firstNumber: Int, secondNumber: Int): Int {
    return firstNumber - secondNumber
}

Parâmetros padrão

Etapa 1

  1. Crie uma função displayAlertMessage() que aceite parâmetros operatingSystem e emailId, ambos do tipo String, e retorne um valor de String.
  2. No corpo da função, use uma expressão de modelo para atualizar a mensagem e a retornar.
fun displayAlertMessage(operatingSystem: String, emailId: String): String {
    return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}

Etapa 2

  • Atribua um valor "Unknown OS" ao parâmetro operatingSystem.
fun displayAlertMessage(
    operatingSystem: String = "Unknown OS",
    emailId: String
): String {
    return "There is a new sign-in request on $operatingSystem for your Google Account $emailId."
}

Pedômetro

Os nomes das funções e variáveis precisam seguir a convenção de concatenação.

Se os nomes tiverem várias palavras, coloque a primeira letra da primeira palavra em letra minúscula, a primeira letra das próximas palavras em maiúscula e remova os espaços entre as palavras.

Exemplos de nomes de função incluem:

  • calculateTip
  • displayMessage
  • takePhoto

Veja alguns exemplos de nomes de variáveis:

  • numberOfEmails
  • cityName
  • bookPublicationDate

Para saber mais sobre nomes, consulte as Regras de nomenclatura (link em inglês).

Não é permitido usar palavras-chave do Kotlin (link em inglês) como nomes de função, porque essas palavras já têm significados específicos na linguagem Kotlin.

O código da solução vai ser parecido com este snippet de código:

fun main() {
    val steps = 4000
    val caloriesBurned = pedometerStepsToCalories(steps)
    println("Walking $steps steps burns $caloriesBurned calories") 
}

fun pedometerStepsToCalories(numberOfSteps: Int): Double {
    val caloriesBurnedForEachStep = 0.04
    val totalCaloriesBurned = numberOfSteps * caloriesBurnedForEachStep
    return totalCaloriesBurned
}

Comparar dois números

  • Crie uma função compareTime() que aceite parâmetros timeSpentToday e timeSpentYesterday, ambos do tipo Int, e retorne um valor Boolean.

A solução depende do operador de comparação >. O operador é avaliado como um valor Boolean, portanto, a função compareTime() simplesmente retorna o resultado de timeSpentToday > timeSpentYesterday.

Por exemplo, se você transmitir um argumento 300 para o parâmetro timeSpentToday e um argumento 250 para o parâmetro timeSpentYesterday, o corpo da função vai ser avaliado para 300 > 250, que retorna um valor true porque 300 é maior que 250.

fun main() {
    println("Have I spent more time using my phone today: ${compareTime(300, 250)}")
    println("Have I spent more time using my phone today: ${compareTime(300, 300)}")
    println("Have I spent more time using my phone today: ${compareTime(200, 220)}")
}

fun compareTime(timeSpentToday: Int, timeSpentYesterday: Int): Boolean {
    return timeSpentToday > timeSpentYesterday
}
Have I spent more time using my phone today: true
Have I spent more time using my phone today: false
Have I spent more time using my phone today: false

Mover o código duplicado para uma função

  1. Crie uma função que mostre os detalhes do clima para a cidade de Ancara após a função main().

Para o nome da função, é possível usar printWeatherForCity() ou algo semelhante.

  1. Chame a função da cidade na função main().

O programa deve mostrar os detalhes meteorológicos de Ancara.

fun main() {
    printWeatherForCity()
}

fun printWeatherForCity() {
    println("City: Ankara")
    println("Low temperature: 27, High temperature: 31")
    println("Chance of rain: 82%")
    println()
}

Agora você pode criar outra função que seja mais flexível para gerar detalhes meteorológicos de outras cidades.

  1. Substitua as partes específicas de Ancara das instruções println() por variáveis.

Lembre-se de usar a convenção de concatenação para os nomes das variáveis e o símbolo $ antes da variável, de modo que o valor dela seja usado no lugar do nome. Veja modelos de string que você aprendeu em um codelab anterior.

fun printWeatherForCity() {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. Mude a definição da função de modo que essas variáveis sejam parâmetros que precisam ser transmitidos para a função quando ela for chamada. Além disso, especifique o tipo de dados para cada parâmetro.

O parâmetro cityName é do tipo String, enquanto os parâmetros lowTemp, highTemp e chanceOfRain são do tipo Int.

Não é necessário usar o valor return na definição da função porque as mensagens são geradas na saída.

fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. Atualize a função main() para chamar a função printWeatherForCity() e transmitir os detalhes do clima de Ancara.

O nome da cidade é "Ankara", a temperatura mínima é 27, a máxima é 31 e a chance de chuva é 82.

fun main() {
    printWeatherForCity("Ankara", 27, 31, 82)
}

fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. Execute o programa para verificar se a saída mostra os detalhes do clima para Ancara.
  2. Chame a função printWeatherForCity() com os detalhes do clima para as outras cidades.
fun main() {
    printWeatherForCity("Ankara", 27, 31, 82)
    printWeatherForCity("Tokyo", 32, 36, 10)
    printWeatherForCity("Cape Town", 59, 64, 2)
    printWeatherForCity("Guatemala City", 50, 55, 7)
}

fun printWeatherForCity(cityName: String, lowTemp: Int, highTemp: Int, chanceOfRain: Int) {
    println("City: $cityName")
    println("Low temperature: $lowTemp, High temperature: $highTemp")
    println("Chance of rain: $chanceOfRain%")
    println()
}
  1. Execute o programa.

Você vai ver o mesmo resultado que o programa original, mas agora o código está mais conciso e não inclui repetições desnecessárias. Todo o código de geração de detalhes meteorológicos de uma cidade é centralizado em um único lugar: a função printWeatherForCity(). Se você quiser mudar a forma como os detalhes meteorológicos são mostrados, pode fazer modificações neles em um só lugar que se aplique a todas as cidades.

13. Mais exercícios

Para praticar mais sobre a linguagem Kotlin, confira a faixa principal de Kotlin da JetBrains Academy. Para ir a um tópico específico, acesse o mapa de conhecimento (links em inglês) e confira a lista de temas abordados na faixa.