1. Antes de começar
Em um codelab anterior, você viu um programa simples que mostrou a mensagem Hello, world!
. Nos programas criados até agora, você aprendeu sobre duas funções:
- Uma função principal
main()
, que é necessária em todo programa Kotlin. Ela é o ponto de entrada, ou ponto de partida, do programa. - Uma função
println()
, chamada na funçãomain()
para gerar texto.
Neste codelab, você vai aprender mais sobre funções.
As funções permitem dividir o código em partes reutilizáveis, em vez de incluir tudo na função main()
. Elas são um elemento essencial dos apps Android, e saber como definir e usá-las é muito importante na jornada para se tornar um desenvolvedor Android.
Pré-requisitos
- Conhecimentos básicos de programação em Kotlin, incluindo variáveis e as funções
println()
emain()
.
O que você vai aprender
- Como definir e chamar suas próprias funções.
- Como retornar de uma função valores que podem ser armazenados em uma variável.
- Como definir e chamar funções com vários parâmetros.
- Como chamar funções com argumentos nomeados.
- Como definir valores padrão para parâmetros de função.
O que é necessário
- Um navegador da Web com acesso ao Playground Kotlin.
2. Definir e chamar uma função
Antes de conhecer mais a fundo as funções, vamos revisar alguns termos básicos.
- A declaração (ou definição) de uma função usa a palavra-chave
fun
e inclui o código entre chaves, que contém as instruções necessárias para executar uma tarefa. - Chamar uma função faz com que todo o código contido nessa função seja executado.
Até agora, você escreveu todo o código na função main()
. Essa função não é chamada em nenhum lugar do código. O compilador Kotlin a usa como ponto de partida. A main()
é usada apenas para incluir outros códigos que você quer executar, como chamadas para a função println()
.
A função println()
faz parte da linguagem Kotlin. No entanto, é possível definir suas próprias funções. Isso permite que o código seja reutilizado se precisar ser chamado mais de uma vez. Veja o exemplo do programa abaixo.
fun main() {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
A função main()
consiste em duas instruções println()
: uma para desejar ao Rover um feliz aniversário e outra que indica a idade dele.
Embora o Kotlin permita colocar todo o código na função main()
, talvez você nem sempre queira fazer isso. Por exemplo, se você também quiser que o programa contenha uma felicitação de ano-novo, a função principal também teria que incluir essas chamadas para println()
. Ou talvez você queira dar parabéns ao Rover várias vezes. É possível simplesmente copiar e colar o código ou criar uma função separada para dar os parabéns. Você vai fazer a segunda opção. A criação de funções separadas para tarefas específicas oferece vários benefícios.
- Código reutilizável: em vez de copiar e colar códigos que você precisa usar mais de uma vez, basta chamar uma função sempre que necessário.
- Legibilidade: garantir que funções realizem apenas uma tarefa específica ajuda outros desenvolvedores, colegas de equipe e até mesmo você no futuro a saber exatamente o que um código faz.
A sintaxe para definir uma função é mostrada no diagrama abaixo.
Para definir uma função, comece com a palavra-chave fun
, seguida pelo nome da função, um conjunto de parênteses de abertura e fechamento e um conjunto de chaves de abertura e fechamento. O código entre chaves é aquele que vai ser executado quando a função for chamada.
Você vai criar uma nova função para remover as duas instruções println()
da função main()
.
- No navegador, abra o Playground Kotlin e substitua o conteúdo pelo código abaixo.
fun main() {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
- Após a função
main()
, defina uma nova função chamadabirthdayGreeting()
. Essa função é declarada com a mesma sintaxe da funçãomain()
.
fun main() {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
fun birthdayGreeting() {
}
- Mova as duas instruções
println()
demain()
para entre as chaves da funçãobirthdayGreeting()
.
fun main() {
}
fun birthdayGreeting() {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
- Na função
main()
, chame abirthdayGreeting()
. O código finalizado ficará assim:
fun main() {
birthdayGreeting()
}
fun birthdayGreeting() {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
- Execute o código. A saída será esta:
Happy Birthday, Rover! You are now 5 years old!
3. Retornar um valor de uma função
Em apps mais complexos, as funções fazem mais do que mostrar um texto.
As funções do Kotlin também podem gerar dados conhecidos como valores de retorno, que são armazenados em uma variável que pode ser usada em outro lugar no código.
Ao definir uma função, é possível especificar o tipo de dado do valor que você quer que ela retorne. O tipo de retorno é especificado colocando dois-pontos (:
) após os parênteses, um único espaço em branco e, em seguida, o nome do tipo (Int
, String
etc.). Um único espaço é colocado entre o tipo de retorno e a chave de abertura. No corpo da função, depois de todas as instruções, você vai usar uma instrução de retorno para especificar o valor que a função retornará. Uma instrução de retorno consiste na palavra-chave return
, seguida pelo valor, como uma variável, que você quer que a função retorne como saída.
A sintaxe para declarar uma função com um tipo de retorno é mostrada abaixo.
O tipo Unit
Se você não especificar um tipo de retorno, o tipo padrão será Unit
. Isso significa que a função não retorna um valor. O Unit
é equivalente a tipos de retorno nulo em outras linguagens, como void
em Java e C; Void
/tupla vazia ()
em Swift; None
em Python etc. Qualquer função que não retorne um valor, vai retornar Unit
implicitamente. Você pode observar isso ao modificar o código para retornar Unit
.
- Ao declarar a função
birthdayGreeting()
, adicione dois pontos após o parêntese de fechamento e especifique o tipo de retorno comoUnit
.
fun main() {
birthdayGreeting()
}
fun birthdayGreeting(): Unit {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
- Execute o código e observe que tudo ainda funciona.
Happy Birthday, Rover! You are now 5 years old!
Especificar o tipo de retorno Unit
em Kotlin é opcional. Para funções que não retornam nada ou retornam Unit
, não é necessário ter uma instrução de retorno.
Retornar uma String
com a função birthdayGreeting()
Para demonstrar como uma função pode retornar um valor, você vai modificar a função birthdayGreeting()
para retornar uma string, em vez de simplesmente mostrar o resultado.
- Substitua o tipo de retorno
Unit
porString
.
fun birthdayGreeting(): String {
println("Happy Birthday, Rover!")
println("You are now 5 years old!")
}
- Execute o código. Você vai encontrar um erro. Se você declarar um tipo de retorno para uma função (por exemplo,
String
), essa função precisará incluir uma instrução dereturn
.
A 'return' expression required in a function with a block body ('{...}')
- Só é possível retornar uma única string de uma função, não duas. Substitua as instruções
println()
por duas variáveis,nameGreeting
eageGreeting,
, usando a palavra-chaveval
. Como você removeu as chamadas paraprintln()
da funçãobirthdayGreeting()
, chamarbirthdayGreeting()
não faz nada ser mostrado na tela.
fun birthdayGreeting(): String {
val nameGreeting = "Happy Birthday, Rover!"
val ageGreeting = "You are now 5 years old!"
}
- Usando a sintaxe de formatação de string que você aprendeu em um codelab anterior, adicione uma instrução
return
para retornar uma string da função que consiste em ambas as mensagens de parabéns.
Para formatar as mensagens em uma linha separada, também é necessário usar o caractere de escape \n
. Ele funciona como o caractere de escape \"
que você conheceu em um codelab anterior. O caractere \n
é substituído por uma nova linha para que as duas mensagens fiquem em linhas separadas.
fun birthdayGreeting(): String {
val nameGreeting = "Happy Birthday, Rover!"
val ageGreeting = "You are now 5 years old!"
return "$nameGreeting\n$ageGreeting"
}
- Na função
main()
, comobirthdayGreeting()
retorna um valor, é possível armazenar o resultado em uma variável de string. Declare uma variável para a mensagem degreeting
usandoval
e armazene o resultado da chamada dabirthdayGreeting()
.
fun main() {
val greeting = birthdayGreeting()
}
- Na função
main()
, chameprintln()
para mostrar a stringgreeting
. A funçãomain()
agora terá a seguinte aparência.
fun main() {
val greeting = birthdayGreeting()
println(greeting)
}
- Execute o código e observe que o resultado é o mesmo de antes. Retornar um valor permite armazenar o resultado em uma variável, mas o que você acha que vai acontecer se você chamar a função
birthdayGreeting()
dentro daprintln()
?
Happy Birthday, Rover! You are now 5 years old!
- Remova a variável e transmita o resultado da chamada da função
birthdayGreeting()
na funçãoprintln()
:
fun main() {
println(birthdayGreeting())
}
- Execute o código e observe a saída. O valor de retorno da chamada
birthdayGreeting()
é transmitido diretamente paraprintln()
.
Happy Birthday, Rover! You are now 5 years old!
4. Adicionar um parâmetro à função birthdayGreeting()
Como visto anteriormente, ao chamar println()
, você pode incluir uma string entre parênteses ou transmitir um valor para a função. O mesmo pode ser feito com a função birthdayGreeting()
. No entanto, primeiro é preciso adicionar um parâmetro à birthdayGreeting()
.
Um parâmetro especifica o nome de uma variável e um tipo de dado que você pode transmitir para uma função como os dados que serão acessados dentro dela. Os parâmetros são declarados entre parênteses após o nome da função.
Cada parâmetro consiste em um nome de variável e um tipo de dado, separados por dois-pontos e um espaço. Vários parâmetros são separados por uma vírgula.
No momento, a função birthdayGreeting()
só pode ser usada para dar parabéns ao Rover. Adicione um parâmetro à função birthdayGreeting()
para que você possa dar parabéns a qualquer nome transmitido à função.
- Dentro dos parênteses da função
birthdayGreeting()
, adicione um parâmetroname
do tipoString
usando a sintaxename: String
.
fun birthdayGreeting(name: String): String {
val nameGreeting = "Happy Birthday, Rover!"
val ageGreeting = "You are now 5 years old!"
return "$nameGreeting\n$ageGreeting"
}
O parâmetro definido na etapa anterior funciona como uma variável declarada com a palavra-chave val
. O valor dela pode ser usado em qualquer lugar na função birthdayGreeting()
. Em um codelab anterior, você aprendeu como inserir o valor de uma variável em uma string.
- Substitua
Rover
na stringnameGreeting
pelo símbolo$
seguido pelo parâmetroname
.
fun birthdayGreeting(name: String): String {
val nameGreeting = "Happy Birthday, $name!"
val ageGreeting = "You are now 5 years old!"
return "$nameGreeting\n$ageGreeting"
}
- Execute o código e observe o erro. Agora que você declarou o parâmetro
name
, é necessário transmitir umaString
ao chamarbirthdayGreeting()
. Quando você chama uma função que usa um parâmetro, um argumento é transmitido para ela. O argumento é o valor transmitido, como"Rover"
.
No value passed for parameter 'name'
- Transmita
"Rover"
para a chamadabirthdayGreeting()
namain()
.
fun main() {
println(birthdayGreeting("Rover"))
}
- Execute o código e observe a saída. O nome "Rover" vem do parâmetro
name
.
Happy Birthday, Rover! You are now 5 years old!
- Como
birthdayGreeting()
recebe um parâmetro, é possível usar um outro nome além de Rover. Adicione outra chamada parabirthdayGreeting()
dentro da chamada paraprintln()
, transmitindo o argumento"Rex"
.
println(birthdayGreeting("Rover"))
println(birthdayGreeting("Rex"))
- Execute o código novamente e observe que a saída é diferente, dependendo do argumento transmitido para
birthdayGreeting()
.
Happy Birthday, Rover! You are now 5 years old! Happy Birthday, Rex! You are now 5 years old!
5. Funções com vários parâmetros
Você já adicionou um parâmetro para mudar os parabéns com base no nome. Também é possível definir mais de um parâmetro para uma função, até mesmo parâmetros de tipos de dados diferentes. Nesta seção, você vai mudar os parabéns para que também mudem de acordo com a idade do cachorro.
As definições dos parâmetros são separadas por vírgulas. Da mesma maneira, ao chamar uma função com vários parâmetros, você também separa os argumentos transmitidos com vírgulas. Vamos ver tudo isso em ação.
- Depois do parâmetro
name
, adicione umage
do tipoInt
à funçãobirthdayGreeting()
. A nova declaração da função precisa ter os dois parâmetros,name
eage
, separados por uma vírgula:
fun birthdayGreeting(name: String, age: Int): String {
val nameGreeting = "Happy Birthday, $name!"
val ageGreeting = "You are now 5 years old!"
return "$nameGreeting\n$ageGreeting"
}
- A nova string de parabéns precisa usar o parâmetro
age
. Atualize a funçãobirthdayGreeting()
para usar o valor do parâmetroage
na stringageGreeting
.
fun birthdayGreeting(name: String, age: Int): String {
val nameGreeting = "Happy Birthday, $name!"
val ageGreeting = "You are now $age years old!"
return "$nameGreeting\n$ageGreeting"
}
- Execute a função e observe os erros na saída:
No value passed for parameter 'age' No value passed for parameter 'age'
- Modifique as duas chamadas para a função
birthdayGreeting()
namain()
para transmitir uma idade diferente para cada cachorro. Transmita5
para a idade do Rover e2
para a idade do Rex.
fun main() {
println(birthdayGreeting("Rover", 5))
println(birthdayGreeting("Rex", 2))
}
- Execute o código. Agora que você transmitiu valores para ambos os parâmetros, a saída precisa refletir o nome e a idade de cada cachorro ao chamar a função.
Happy Birthday, Rover! You are now 5 years old! Happy Birthday, Rex! You are now 2 years old!
Assinatura da função
Até agora, você aprendeu como definir o nome, as entradas (parâmetros) e as saídas da função. O nome da função com as entradas (parâmetros) é conhecido coletivamente como a assinatura da função. A assinatura da função consiste em tudo que vem antes do tipo de retorno e é mostrada no snippet de código abaixo.
fun birthdayGreeting(name: String, age: Int)
Os parâmetros separados por vírgulas, às vezes, são chamados de lista de parâmetros.
Muitas vezes, você vai encontrar esses termos na documentação de códigos criados por outros desenvolvedores. A assinatura da função informa o nome da função e os tipos de dados que podem ser transmitidos.
Você aprendeu várias novas sintaxes para definir funções. O diagrama abaixo mostra um resumo da sintaxe de funções.
6. Argumentos nomeados
Nos exemplos anteriores, não era necessário especificar os nomes dos parâmetros, name
ou age
, ao chamar uma função. No entanto, você pode fazer isso se preferir. Por exemplo, você pode chamar uma função com vários parâmetros ou transmitir os argumentos em uma ordem diferente, como colocar o parâmetro age
antes do name
. Se você incluir o nome do parâmetro ao chamar a função, ele será um argumento nomeado (link em inglês). Tente usar um argumento nomeado com a função birthdayGreeting()
.
- Modifique a chamada para o Rex usando argumentos nomeados, conforme mostrado neste snippet de código. Para fazer isso, inclua o nome do parâmetro seguido de um sinal de igual e, em seguida, o valor (por exemplo,
name = "Rex"
).
println(birthdayGreeting(name = "Rex", age = 2))
- Execute o código e observe que a saída se mantém inalterada:
Happy Birthday, Rover! You are now 5 years old! Happy Birthday, Rex! You are now 2 years old!
- Reorganize os argumentos nomeados. Por exemplo, coloque o argumento nomeado
age
antes doname
.
println(birthdayGreeting(age = 2, name = "Rex"))
- Execute o código e observe que a saída permanece a mesma. Mesmo que você tenha mudado a ordem dos argumentos, os mesmos valores são transmitidos para os mesmos parâmetros.
Happy Birthday, Rover! You are now 5 years old! Happy Birthday, Rex! You are now 2 years old!
7. Argumentos padrão
Os parâmetros de função também podem especificar argumentos padrão. Talvez o Rover seja seu cachorro favorito, ou você espera que uma função seja chamada com argumentos específicos na maioria dos casos. Ao chamar uma função, você pode omitir argumentos para os quais há um padrão. Nesse caso, o padrão vai ser usado.
Para adicionar um argumento padrão, coloque o operador de atribuição (=
) após o tipo de dado do parâmetro e o defina como um valor. Modifique seu código para usar um argumento padrão.
- Na função
birthdayGreeting()
, defina o parâmetroname
com o valor padrão"Rover"
.
fun birthdayGreeting(name: String = "Rover", age: Int): String {
return "Happy Birthday, $name! You are now $age years old!"
}
- Na primeira chamada para
birthdayGreeting()
para o Rover namain()
, defina o argumento chamadoage
como5
. Como o parâmetroage
é definido depois doname
, você precisa usar o argumento nomeadoage
. Sem os argumentos nomeados, o Kotlin presume que a ordem dos argumentos seja a mesma em que os parâmetros são definidos. O argumento nomeado é usado para garantir que o Kotlin esteja esperando um valorInt
para o parâmetroage
.
println(birthdayGreeting(age = 5))
println(birthdayGreeting("Rex", 2))
- Execute o código. A primeira chamada para a função
birthdayGreeting()
mostra "Rover" como o nome, porque você não especificou o nome. A segunda chamada parabirthdayGreeting()
ainda usa o valorRex
, que você transmitiu para oname
.
Happy Birthday, Rover! You are now 5 years old! Happy Birthday, Rex! You are now 2 years old!
- Remova o nome da segunda chamada para a função
birthdayGreeting()
. Novamente, como oname
é omitido, é necessário usar um argumento nomeado para a idade.
println(birthdayGreeting(age = 5))
println(birthdayGreeting(age = 2))
- Execute o código e observe que agora as duas chamadas para
birthdayGreeting()
mostram "Rover" como o nome, porque nenhum argumento nomeado foi transmitido.
Happy Birthday, Rover! You are now 5 years old! Happy Birthday, Rover! You are now 2 years old!
8. Conclusão
Parabéns! Você aprendeu a definir e chamar funções no Kotlin.
Resumo
- As funções são definidas usando a palavra-chave
fun
e contém partes de código reutilizáveis. - As funções facilitam a manutenção de programas maiores e evitam a repetição desnecessária de código.
- As funções podem retornar um valor que pode ser armazenado em uma variável para uso futuro.
- As funções podem ter parâmetros, que são variáveis disponíveis no corpo da função.
- Argumentos são os valores que você transmite quando chama uma função.
- Você pode nomear argumentos ao chamar uma função. Ao usar argumentos nomeados, é possível reordenar os argumentos sem afetar a saída.
- É possível especificar um argumento padrão para omitir o argumento ao chamar uma função.