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
Top comments (0)