Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Kotlin

Kotlin a Partir do Princípio: Pacotes e Funções Básicas

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Kotlin From Scratch.
Kotlin From Scratch: Ranges and Collections
Kotlin From Scratch: More Fun With Functions

Portuguese (Português) translation by Luis Drum (you can also view the original English article)

Kotlin é uma linguagem moderna de programação que é compilada em bytecode Java. É gratuita e de código aberto e promete fazer a codificação para o Android ainda mais divertida.

No artigo anterior, você aprendeu sobre sequências e coleções em Kotlin. Neste tutorial, vamos continuar a aprender a linguagem, observando como organizar o código usando pacotes e depois passar para uma introdução às funções em Kotlin.

1. Pacotes

Se você estiver familiarizado com Java, você sabe que no Java são usados pacotes para agrupar classes relacionadas; por exemplo, o pacote java.util possui um número de classes utilitárias. Pacotes são declarados com a palavra-chave package, e qualquer arquivo de Kotlin com uma declaração de package no início pode conter declarações de funções, classes ou interfaces.

Declaração

Olhando para o código abaixo, declaramos um pacote com.chikekotlin.projectx usando a palavra-chave  package. Além disso, nós declaramos uma classe MyClass (discutiremos classes em Kotlin em posts futuros) dentro deste pacote.

Agora, o nome totalmente qualificado para a classe MyClass é com.chikekotlin.projectx.MyClass.

No código acima, criamos uma função de nível superior (vamos chegar a isso em breve). Então, da mesma forma que para MyClass, o nome totalmente qualificado para a função saySomething() é com.chikekotlin.projectx.saySomething.

Importações

Em Kotlin, usamos a declaração import para permitir que o compilador localize as classes, funções, interfaces ou objetos a serem importados. Em Java, por outro lado, nós não podemos importar diretamente funções ou métodos — apenas classes ou interfaces.

Nós usamos import para acessar uma função, interface, classe ou objeto fora do pacote onde foi declarado.

No trecho de código acima, nós importamos a função saySomething() de um pacote diferente, e em seguida executamos essa função.

Kotlin também suporta importações curinga usando o operador *. Isto irá importar todas as classes, interfaces e funções declaradas no pacote ao mesmo tempo. Isso não é recomendado, porém — geralmente é melhor explicitar suas importações.

Importação de Codinome

Quando você tem bibliotecas que têm classes ou nomes de função conflitantes (por exemplo, cada uma delas declarar uma função com o mesmo nome), você pode usar a palavra-chave as para dar àquela entidade importada um nome temporário.

Observe que o nome temporário é usado somente dentro do arquivo onde ele foi atribuído.

2. Funções

Uma função agrupa uma série de instruções de código que executam uma tarefa.Os detalhes da implementação da função estão ocultos do chamador.

Em Kotlin, funções são definidas usando a palavra-chave fun, como mostrado no exemplo a seguir:

No código acima, definimos uma função simples hello() com um único parâmetro name do tipo String. Essa função retorna um tipo String. O formato de definição de parâmetros para funções é name: type, por exemplo, age: Int, price: Double, student: StudentClass.

A função acima é semelhante a anterior, mas observe que esta tem um tipo de retorno Unit. Porque esta função não retorna nenhum valor significativo para nós — ela só imprime uma mensagem — seu tipo de retorno é Unit por padrão. Unit é um objeto de Kotlin (discutiremos objetos de Kotlin em posts posteriores) que é similar aos tipos Void em Java e C.

Note que se você não declarar explicitamente o tipo de retorno como Unit, o tipo é inferido pelo compilador.

Funções de Linha Única

Funções de linha única ou de uma linha são funções que são apenas simples expressões. Nessa função, podemos livrar-nos das chaves e usar o símbolo = antes da expressão. Em outras palavras, nos livramos do bloco de função.

A função acima pode ser encurtada em uma única linha:

Olhando para a função atualizada acima, você pode ver que nós fizemos nosso código mais conciso, removendo as chaves {}, a palavra-chave return e também o tipo de retorno (que é inferido pelo compilador).

Você ainda pode incluir o tipo de retorno para ser mais explícito, se você quiser.

Parâmetros Nomeados

Parâmetros nomeados permitem funções mais legíveis, nomeando os parâmetros que estão sendo passados para uma função quando chamada.

No exemplo a seguir, criamos uma função que imprime meu nome completo.

Para executar a função acima, nós apenas a chamaríamos assim:

Olhando para a chamada de função acima, nós não sabemos quais argumentos de tipo String equivalem a quais parâmetros da função (embora alguns IDEs como o IntelliJ IDEA possam nos ajudar). Os usuários da função terão que olhar para a assinatura da função (ou o código-fonte) ou a documentação para saber a qual cada parâmetro corresponde.

Na segunda chamada de função acima, nós fornecemos os nomes dos parâmetros antes dos valores dos argumentos. Você pode ver que essa chamada de função é mais clara e mais legível do que a anterior. Esta maneira de chamar funções ajuda a reduzir a possibilidade de bugs que podem acontecer quando os argumentos do mesmo tipo são trocados por engano.

O chamador também pode alterar a ordem dos parâmetros usando parâmetros nomeada. Por exemplo:

No código acima, nós trocamos a posição do argumento firstName  com lastName. A ordem dos argumentos com parâmetros nomeados não importa, porque o compilador irá mapear cada um para o parâmetro de função correto.

Parâmetros Padrão

Em Kotlin, poderemos dar a uma função valores padrão para qualquer um dos seus parâmetros. Esses valores padrão serão usados se nada é atribuído aos argumentos durante a chamada de função. Para fazer isso em Java, teríamos de criar diferentes métodos sobrecarregados.

Aqui, em nosso método calCircumference(), nós modificamos o método adicionando um valor padrão para o parâmetro pi —Math.PI, uma constante do pacote java.lang.Math.

Quando nós chamamos esta função, podemos passar nosso valor aproximado de pi ou usar o padrão.

Vamos ver outro exemplo.

No código a seguir, nós tentamos chamar a função, mas ele não vai compilar:

Na chamada de função acima, estou passando meu primeiro nome e sobrenome para a função e esperando usar o valor padrão para o nome do meio. Mas isso não vai compilar porque o compilador está confuso.  Não sabe para que serve o argumento "Mgbemena" — é para o middleName ou para o parâmetro lastName?

Para resolver esse problema, podemos combinar parâmetros nomeados e parâmetros padrão.

Interoperabilidade Java

Dado que o Java não suporta valores de parâmetro padrão em métodos, você precisará especificar explicitamente todos os valores de parâmetro, quando você chamar uma função de Kotlin a partir do Java. Mas o Kotlin nos fornece uma funcionalidade para facililtar para os chamadores de Java, anotando a função de Kotlin com @JvmOverloads. Esta anotação irá instruir o compilador de Kotlin para gerar as funções Java sobrecarregadas para nós.

No exemplo a seguir, nós anotamos a função calCirumference() com @JvmOverloads.

O código a seguir foi gerado pelo compilador Kotlin para que os chamadores Java possam então escolher qual chamar.

Na última definição de método Java gerada, o parâmetro de pi foi omitido. Isto significa que o método usará o valor de pi padrão.

Argumentos Ilimitados

Em Java, podemos criar um método para receber um número indeterminado de argumentos, incluindo reticências (...) depois de um tipo na lista de parâmetros do método. Este conceito também é suportado por funções Kotlin com o uso do modificador vararg seguido do nome do parâmetro.

O modificador vararg permite que os chamadores passem os argumentos em uma lista separada por vírgulas. Nos bastidores, esta lista de argumentos irá ser empacotada em uma matriz.

Quando uma função tem vários parâmetros, o parâmetro vararg é normalmente o último. Também é possível ter parâmetros após o vararg, mas você precisará usar parâmetros nomeados para especificá-los quando você chamar a função.

Por exemplo, no código acima, o parâmetro com o modificador vararg está na última posição em uma lista de  múltiplos parâmetros (isto é o que geralmente fazemos). Mas e se não o queremos na última posição? No exemplo a seguir, ele está na segunda posição.

Como se pode observar no código atualizado acima, usamos argumentos nomeados no último parâmetro para resolver isto.

Operador de Propagação

Digamos que queremos passar uma matriz de inteiros para nossa função printNumbers(). A função espera que os valores sejam expostos em uma lista de parâmetros, no entanto. Se você tentar passar a matriz diretamente para printNumbers(), você verá que ela não vai compilar.

Para resolver este problema, precisamos usar o operador de propagação *. Este operador irá descompactar a matriz e em seguida, passar os elementos individuais como argumentos para a função, para nós.

Inserindo o operador de propagação * na frente do intsArray na lista de argumentos da função, o código agora compila e produz o mesmo resultado como se passassemos os elementos de intsArray como uma lista de argumentos separada por vírgulas .

Retornar Valores Múltiplos

Às vezes nós queremos retornar vários valores de uma função. Uma maneira é usar o tipo Pair em Kotlin para criar um Pair e retorná-lo. Essa estrutura Pair inclui dois valores que podem ser acessados mais tarde. Este tipo de Kotlin pode aceitar quaisquer tipos que você fornecer ao seu construtor. E, além do mais, os dois tipos nem precisam ser o mesmo.

Na função acima, construímos um novo Pair, passando as variáveis userName e userState como o primeiro e segundo argumento respectivamente para seu construtor e  então retornamos este Pair para o chamador.

Outra coisa a observar é que usamos uma função chamada require() na função getUserNameAndState(). Esta função auxiliar da biblioteca padrão é usada para dar aos chamadores de função uma pré-condição para atender, senão será lançada uma IllegalArgumentException (discutiremos exceções em Kotlin em um post futuro). O segundo argumento opcional para require() é uma função literal de retornar uma mensagem a ser exibida se a exceção é lançada. Por exemplo, chamando a função getUserNameAndState() e passando -1 como um argumento irá disparar:

IntelliJ IDEA code execution result

Recuperar Dados de Pair

No código acima, acessamos o primeiro e o segundo valor do tipo Pair usando suas propriedades first e second.

No entanto, há uma maneira melhor de fazer isso: desestruturação.

O que fizemos no código atualizado acima é atribuir diretamente o primeiro e segundo valores do tipo Pair retornados para as variáveis namestate respectivamente. Esse recurso é chamado de declaração de desestruturação.

Valores de Retorno Triplo e Além

Agora, se você quiser retornar três valores de uma vez? Kotlin nos fornece outro tipo útil chamado Triple.

Tenho certeza que alguns de vocês estão se perguntando o que fazer se você quiser mais do que três valores de retorno. A resposta para isso estará em um próximo post, quando discutirmos as classes de dados de Kotlin.

Conclusão

Neste tutorial, você aprendeu sobre os pacotes e as funções básicas da linguagem de programação Kotlin. No próximo tutorial da série Kotlin a Partir do Princípio, você aprenderá mais sobre funções em Kotlin. Te vejo em breve!

Para saber mais sobre a linguagem Kotlin, eu recomendo visitar a documentação de Kotlin. Ou confira alguns dos nossos outros posts de desenvolvimento de apps Android aqui no Envato Tuts +!

Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.