Conhecendo o Kotlin
Tags: programming, kotlin
Published: 2022-09-13 11:18:44

Se como eu lhe foi dado o desafio de aprender Kotlin e já trabalhar com a linguagem ou apenas por conhecimento próprio, espero que este post lhe ajude.
 
Iniciando pela parte técnica o Kotlin se trata de uma linguagem de _tipagem estática_, os tipos das variáveis são checados durante a **compilação** gerando um erro se houver troca de tipo. Sua tipagem é forte, o que significa que **não** possui flexibilidade nas operações entre variáveis de tipos diferentes.

```
val nomeOperario: String = "José"
val horasExtra: Int = 1000
println(nomeOperario + horasExtra) //gera um erro na compilacao
```

A declaração de variáveis, como no exemplo acima, usa a palavra chave _val_ ou _var_. A primeira **não** permite alterar o valor que lhe foi atribuído, equivalente ao final em _java_, a última permite que o valor seja alterado após declarado.

O ponto e vírgula ';' no final da linha de trecho é opcional, porém para aproveitar a sintaxe enxuta da linguagem é [indicado não adicionar](https://kotlinlang.org/docs/coding-conventions.html#semicolons).

Um detalhe importante é que o Kotlin **exige** que um valor seja atribuído a variável durante sua declaração.

A visibilidade default das variáveis é _public_.

No Kotlin temos inferência de tipo, porém podemos deixar o valor explícito com dois pontos ':' seguido do tipo.

E como resultado temos:

`val nomeOperario: String = "José"`

Já que estamos falando de variáveis uma opção interessante para a concatenação de variáveis a _String_ é a utilização do _String template_, basta adicionar um cifrão '$' na frente do nome da variável para a concatenação:

`println("Senhor(a) $nomeOperario ...") // Senhor(a) José ...` 

Para realizar a concatenação com a propriedade de um objeto é similar, porém com o objeto e propriedade entre chaves '{':

`println("Tamanho nome: ${nomeOperario.length}") // Tamanho nome: 4`

Caso necessite escapar caracteres especiais podemos usar o _raw Strings_, adicionamos a _string_ entre um par de 3 aspas duplas:

`val workspace = """/home/dev/workspace"""`

Inclusive podemos utilizar as 3 aspas duplas para ter uma quebra de linha:

```
val cargaSemanal = """Fixadas 30 horas semanais com opções:
I. De segunda a sexta com 6(seis) horas diárias"""
```

Após esta breve visão geral das variáveis, podemos falar sobre os métodos.

Para a declaração do método se inicia com a visibilidade do método, quando omissa a default é _public_, palavra reservada 'fun' seguido pelo nome do método acompanhado pela abertura e fechamento de parênteses '(', quando houverem parâmetros estes vão entres os parênteses. Caso possua um retorno, dois pontos ':' são adicionados após o parêntese de fechamento seguido pelo tipo do retorno. O retorno quando não especificado é do tipo _Unit_. 

```
fun salvarReajusteSalarial(): Boolean {
    //realiza reajuste adequado ao operario
}
```
Os parâmetros dos métodos necessitam terem seus tipos indicados, com o nome do parâmetro acompanhado por dois pontos e seguido pelo seu tipo:

```
fun logarNotificacao(emailOperario: String, log: Logger): String {
    //loga notificao c sucesso
}
```
O Kotlin nos permite informar labels(named arguments) nos argumentos, e com isto ao passar para o método podemos alterar a ordem.

`logarNotificacao(log = logger, emailOperario = email)`

A [convenção da linguagem](https://kotlinlang.org/docs/coding-conventions.html#named-arguments) inclusive recomenda o uso de named arguments quando houverem mais de um parâmetro do mesmo tipo ou para parâmetros Booleanos.

Já que estamos falando de parâmetros, vamos falar dos construtores no Kotlin. A linguagem nos da a opção de dois tipos de construtores.
O primário, que definimos ao lado do nome da classe, no header, onde as parâmetros são declaradas dentro dos parênteses. 

`class Operario constructor(nome: String) {/*...*/}`

Caso o construtor não possua anotações ou modificador de visibilidade podemos omitir a palavra chave _constructor_:

```
class Beneficio(
    val nome: String, 
    val tipo: TipoBeneficio,
    val desconto: Boolean = false
) {
  /*...*/
}
```
No exemplo acima, além do omissão da palavra chave _constructor_ os parâmetros recebidos pelo construtor já foram declarados como propriedade da classe ao adicionar a palavra chave _val_, também é possível utilizar _var_.

Um detalhe para que a [convenção da lingaguem](https://kotlinlang.org/docs/coding-conventions.html#class-headers) recomenda uma quebra de linha nos parâmetros, quando houverem muitos, além do parênteses que fecha em uma nova linha. 
É possível declarar um valor default, como no exemplo, com a propriedade booleana _desconto_.

Caso exista alguma lógica que precisa ser realizada no construtor podemos criar um bloco init dentro da classe.

```
class Beneficio(
    val titulo: String, 
    val tipo: TipoBeneficio,
    val desconto: Boolean = false
) {
  
  init {
    //realiza alguma logica com alguma das propriedades
  }
}
```
Como segunda opção temos o construtor secundário, onde podemos implementar alguma lógica existente dentro de um bloco _constructor_:

```
class Beneficio() {
  
  var titulo: String = ""   

  constructor(tituloBeneficio: String) {
    // implementa alguma logica com a propriedade
  }
}
```
O mais comum que vamos ver no dia a dia irá ser o uso do construtor primário.

E para finalizar, vamos abordar como o Kotlin trabalha com encapsulamento através dos _getters_ e _setters_.

Por sua existência implícita não se costuma criar getters e setters no Kotlin. O _get_ e _set_ vão possuir as mesmas visibilidades das propriedades a que se referem. 

Porém as visibilidades do _get_ e _set_ podem ser customizadas.

```
 var titulo: String = ""
    private set
```
No exemplo acima o _get_ para _titulo_, assim como a propriedade, vão ter uma visibilidade pública, já o _set_ passou a ser _private_. Logo pode ser lida por qualquer um, porém apenas modificada dentro da classe.

E para os casos em que precisamos adicionar lógica aos _get_ e _set_?
O Kotlin nos permite customizar isto também:

```
var titulo: String = ""
  set(tituloBeneficio) {
    if(tituloBeneficio.length <= tamanhoMaximoPermitido) {
      field = tituloBeneficio
    }
  }
```
No exemplo temos a customização de uma lógica ao _set_ da propriedade _titulo_. O interessante de notar aqui é a palavra chave _field_, que se refere a propriedade em questão, _titulo_.
Portanto, no exemplo temos uma validação da quantidade de caracteres do valor recebido(_tituloBeneficio_), para então a atribuição a propriedade _titulo_ representado pela palavra chave _field_.

Concluo aqui este post onde me preocupei em trazer pontos do Kotlin diferentes da maioria das linguagens. A linguagem traz outros pontos interessantes e de destaque, porém creio ser melhor abordar em outras postagens.

Obrigado pelo seu tempo e se pensa que ficou faltando algo, aceito sugestões.