Funções
Declaração, parâmetros, retorno e funções de expressão única.
Sintaxe
Em Kotlin, as funções são declaradas usando a palavra-chave fun:
fun add() {
// ...
}
Você pode definir parâmetros para a função usando a notação Pascal, name: type. Os parâmetros são separados por
vírgulas, e cada parâmetro deve ser explicitamente tipado:
fun add(augend: Int, addend: Int): Int {
return augend + addend
}
Quando uma função retorna uma única expressão, as chaves podem ser omitidas, e o corpo é especificado após um =:
fun add(augend: Int, addend: Int): Int = augend + addend
Para fazer a chamada da função:
add(1, 1)
Ou usando argumentos nomeados:
add(augend = 1, addend = 1)
Exemplo completo:
fun add(augend: Int, addend: Int): Int = augend + addend
fun main() {
println(add(1, 1)) // 2
println(add(augend = 1, addend = 1)) // 2
}
Nota
Usar argumentos nomeados pode ser útil quando uma função tem muitos parâmetros, facilitando a associação de valores aos argumentos.
Funções de extensão
Kotlin permite adicionar funcionalidades a classes existentes sem alterá-las diretamente, usando extension
functions.
Isso é útil para estender o comportamento de objetos existentes sem modificá-los ou criar novos tipos.
Para criar uma função de extensão, a sintaxe é:
fun ClassName.newFunctionName(arguments.. .) {
// ...
}
Vamos criar uma função de extensão chamada screaming para a classe String, que retorna a string em letras
maiúsculas, seguida por três pontos de exclamação:
fun String.screaming(): String = uppercase() + "!!!"
"Hello World".screaming()
Exemplo completo:
fun String.screaming(): String = uppercase() + "!!!"
fun main() {
println("Hello World".screaming()) // HELLO WORLD!!!
}
Operadores aritméticos
Kotlin permite que você sobrescreva operadores, fornecendo implementações personalizadas para operadores como + ou
*. Essas funções são declaradas usando operator fun:
data class BigNumber(val value: Int) {
operator fun div(divisor: BigNumber): Int = value / divisor.value
operator fun plus(addend: BigNumber): Int = value + addend.value
operator fun minus(subtrahend: BigNumber): Int = value - subtrahend.value
operator fun times(multiplier: BigNumber): Int = value * multiplier.value
}
Exemplo completo:
data class BigNumber(val value: Int) {
operator fun div(divisor: BigNumber): Int = value / divisor.value
operator fun plus(addend: BigNumber): Int = value + addend.value
operator fun minus(subtrahend: BigNumber): Int = value - subtrahend.value
operator fun times(multiplier: BigNumber): Int = value * multiplier.value
}
fun main() {
val a = BigNumber(10)
val b = BigNumber(5)
println(a + b) // 15
println(a - b) // 5
println(a * b) // 50
println(a / b) // 2
}
Funções de alta ordem e lambdas
Funções de alta ordem
Em Kotlin, funções podem ser tratadas como cidadãos de primeira classe, ou seja, podem ser usadas como argumentos ou valores de retorno de outras funções.
Como Kotlin é uma linguagem estaticamente tipada, você precisa definir os tipos dos parâmetros e do retorno da função, usando function types.
fun applyDiscount(discount: Int): (Double) -> Double {
val percentage = discount.toDouble() / 100
return { value -> value - (percentage * value) }
}
Aqui, a função applyDiscount retorna uma função que recebe um Double e também retorna um Double.
val discountOf15Percent = applyDiscount(discount = 15)
var amount = 3459.99
amount = discountOf15Percent(amount)
Exemplo completo:
fun applyDiscount(discount: Int): (Double) -> Double {
val percentage = discount.toDouble() / 100
return { value -> value - (percentage * value) }
}
fun main() {
val discountOf15Percent = applyDiscount(discount = 15)
var amount = 3459.99
amount = discountOf15Percent(amount)
println(amount) // 2940.9915
}
Lambdas
Funções podem ser instanciadas de duas maneiras: usando expressões lambda ou funções anônimas.
val plusOneLambda = { value: Int -> value + 1 }
val plusOneAnonymous = fun(value: Int): Int {
return value + 1
}
Essas funções podem ser invocadas diretamente ou usando o operator invoke:
plusOneLambda(1)
plusOneLambda.invoke(1)
plusOneAnonymous(2)
plusOneAnonymous.invoke(2)
Também é possível criar tipos nomeados para funções usando typealias:
typealias Sum = (Int) -> Int
val plusOneLambda: Sum = { value: Int -> value + 1 }
Exemplo completo:
typealias Sum = (Int) -> Int
fun main() {
val plusOneLambda: Sum = { value: Int -> value + 1 }
val plusOneAnonymous = fun(value: Int): Int {
return value + 1
}
println(plusOneLambda(1)) // 2
println(plusOneLambda.invoke(1)) // 2
println(plusOneAnonymous(2)) // 3
println(plusOneAnonymous.invoke(2)) // 3
}