Sobrecarga de operadores do Kotlin
Alex Felipe
Posted on June 6, 2023
Um detalhe bastante curioso no Kotlin é que podemos "somar", "subtrair" ou fazer diversas operações com os nossos objetos. Um exemplo bastante interessante seria a soma de listas:
val words = listOf("alex", "felipe")
val numbers = listOf(1, 2, 3)
val someList = words + numbers
println(someList)
println(words)
println(numbers)
Qual o resultado você espera? Vejamos:
[alex, felipe, 1, 2, 3]
[alex, felipe]
[1, 2, 3]
Olha que interessante! Uma nova lista foi criada adicionando os itens de cada lista, e mais, a soma não é restrita apenas entre as listas, podemos somar com qualquer objeto, até mesmo os nossos:
data class User(
val id: Long,
val name: String
)
val numbersWithUser = listOf(1, 2) + User(
id = 1,
name = "alexfelipe"
)
val wordsWithNumber = listOf(
"alex",
"felipe"
) + 1
println(numbersWithUser)
println(wordsWithNumber)
E o resultado que temos é:
[1, 2, User(id=1, name=alexfelipe)]
[alex, felipe, 1]
Neste momento você pode pensar:
"Como isso é possível?" 🤔
Conhecendo a sobrecarga de operadores
Essa funcionalidade é conhecida como sobrecarga de operadores ou operator overloading, embora o nome poça assustar, basicamente, são métodos "especiais" com a keyword operator
que permitem adicionar o comportamento que desejamos.
Vamos considerar o exemplo do +
, ele é traduzido para o método plus()
. Podemos até mesmo ver algumas implementações na interface de Collection
:
public operator fun <T> Collection<T>.plus(element: T): List<T> {
val result = ArrayList<T>(size + 1)
result.addAll(this)
result.add(element)
return result
}
public operator fun <T> Iterable<T>.plus(elements: Iterable<T>): List<T> {
if (this is Collection) return this.plus(elements)
val result = ArrayList<T>()
result.addAll(this)
result.addAll(elements)
return result
}
Veja que tem mais de uma implementação e é por isso que podemos somar listas com listas ou listas com objetos e por ai vai... Aqui você pode ver alguns operadores comuns:
Expressão | Traduzido para |
---|---|
a + b |
a.plus(b) |
a - b |
a.minus(b) |
a * b |
a.times(b) |
a / b |
a.rem(b) |
a..b |
a.rangeTo(b) |
Em outras palavras, se você é capaz de fazer alguma dessas operações com objetos em Kotlin, é porque existe essa sobrecarga!
Implementando sobrecarga de operadores
Inclusive, podemos implementar operadores em nossas classes:
data class Product(
val id: Long,
val name: String,
val description: String
)
class Cart(
val products: List<Product> = listOf()
) {
operator fun plus(product: Product): Cart =
Cart(products + product)
}
Nesta implementação, podemos criar novos carrinhos com os produtos que desejamos somar:
val cart = Cart()
val cartWithKeyboard = cart + Product(
id = 1,
name = "Teclado mecânico",
description = "Teclado com switches brown"
)
println(cartWithKeyboard.products)
val cartWithTShirt = cartWithKeyboard + Product(
id = 2,
name = "Camiseta",
description = "Material 100% algodão"
)
println(cartWithTShirt.products)
Olha só o resultado que temos:
[Product(id=1, name=Teclado mecânico, description=Teclado com switches brown)]
[Product(id=1, name=Teclado mecânico, description=Teclado com switches brown), Product(id=2, name=Camiseta, description=Material 100% algodão)]
Interessante, né? Outras possibilidades de implementação seriam:
- somar objetos de pedidos e o retorno ser um resumo com todos os produtos, quantidades e valores somados.
- somar objetos de pagamentos ou taxas para obter o valor final com as adições
- somar um usuário e um produto para criar um pedido
Enfim, uma série de ações comuns no nosso dia a dia.
Outros casos de uso de operadores
Atualmente existem diversas implementações de operadores, se observarmos a própria Collection
, identificamos que é possível subtrair também:
val words = listOf("alex", "felipe", "instrutor", "alura") - "felipe"
val numbers = listOf(1, 2, 3) - 2
println(words)
println(numbers)
Veja o resultado:
[alex, instrutor, alura]
[1, 3]
Ou seja, uma forma mais sucinta de criar uma lista nova sem os elementos que não queremos!
E não para por aqui, se pegarmos classes como BigDecimal
, podemos até mesmo fazer operações aritméticas sem problemas:
val total = BigDecimal("2.99") + BigDecimal("4.35")
println(total)
E chegamos no seguinte resultado:
7.34
O mesmo resultado sem a sobrecarga de operador seria assim:
val total = BigDecimal("2.99")
.add(BigDecimal("4.35"))
Para saber mais: outros tipos de operadores
Neste artigo foquei na sobrecarga de operadores aritméticos, mas existem outras possibilidades, operações unárias e binárias, sendo que as aritméticas fazem parte das binárias.
O que achou da sobrecarga de operadores no Kotlin? Já usava no seu código? Compartilhe sua experiência nos comentários
Posted on June 6, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
November 23, 2024