No primeiro capítulo, abordámos valores compostos. Nesta secção iremos abordar como enriquecer tipos de valores compostos com funções.
Para ilustração, utilizaremos o tipo de valor Point que representa uma coordenada cartesiana.
Utilizando a forma de definir funções já abordada, podemos ter a definição da seguinte função para somar dois pontos.
Esta forma de somar pontos não tem nenhum problema, porém, vamos observá-la por comparação às operações aritméticas. Os valor elementares (Int, Double, etc) têm associadas a operações que nos permitem obter outros valores. Essas operações são no fundo funções, que são invocadas com uma sintaxe própria. Por exemplo, podemos pensar em a + b como sendo uma invocação de uma função que soma dois números a e b (plus(a, b) — notação prefixa (ou Polaca) – “mais a e b”), devolvendo um novo valor resultante da adição.
Outra forma de conceber a + b, equivalente à anterior, é que estamos a somar a com o valor de b, obtendo um novo valor. Na sintaxe de Kotlin, isso será expresso na forma a.plus(b). Note-se que o argumento a é “movido” para o início da expressão, e ficamos com uma ordem de operandos e operadores em linha com a + b, e por conseguinte, mais aproximada da forma como falamos (“a mais b” — notação infixa).
Funções associadas a tipos
Veremos então como podemos alcançar a possibilidade de manipular valores compostos com a forma infixa. A definição de um tipo composto pode incluir definições funções (entre as chavetas), como no seguinte exemplo, onde é definida uma função equivalente à sum acima.
Ao utilizar esta forma, o que está a acontecer no fundo é uma função que implicitamente tem um parâmetro this (palavra reservada, e por isso, o código seguinte não seria válido). “This” significa “este”, e logo, refere-se ao valor onde a função for invocada (a no caso acima).
Desta forma, utilizamos this para nos referirmos ao valor onde a função foi invocada (lado esquerdo).
A utilização de this pode ser omitida quando o campo referido não tem o mesmo identificador que um parâmetro da função, e logo, não constituindo ambiguidade. Por outro lado, this pode ser utilizado de forma isolada se pretendermos devolver o próprio valor, ou invocar uma função sobre o mesmo.
Exemplo: Tipo de valor composto para pontos cartesianos com funções associadas. O próprio valor (ou o passado como argumento) são devolvidos quando a soma não resulta num valor diferente. A função para cálculo da distância utiliza funções da biblioteca de matemática (kotlin.math).
Invocação com notação infixa
Tal como ilustrado no exemplo acima, podemos utilizar o modificador infix para indicar que a função pode ser invocada com notação infixa. Isto só se aplica no caso de funções com exatamente um parâmetro.
Esta possibilidade sintática permite que o nome da função seja utilizado como se se tratasse de um operador (+, -, etc). A parte esquerda é o valor cujo tipo define a função, o operador corresponde ao nome da função , e a parte direita consiste no argumento (para o parâmetro único).
Utilização de operadores existentes
Tal como os valores numéricos utilizam operadores com os símbolos +, -, etc, também os tipos de valor que definimos o podem fazer. Para tal, recorremos ao modificador operator seguido da definição de uma função com identificador predefinido para cada operador. No caso do operador binário + é plus, e do operador binário - é minus.
Exemplo: Continuação da classe anterior, definindo dois operadores (+ e -) com base nas funções existentes.
O acrescento apresentado no exemplo permitirá que os pontos possam ser somados e subtraídos utilizando a mesma notação que os números.
Associar funções a tipos de valores permite uma estruturação do código que está na base da programação orientada por objetos, a desenvolver mais à frente.