Funções de Infix no Kotlin
1. Introdução
O Kotlin é uma linguagem que adiciona muitos recursos novos para permitir a criação de códigos mais limpos e fáceis de ler.
Isso, por sua vez, torna nosso código significativamente mais fácil de manter e permite um melhor resultado final de nosso desenvolvimento. Infix notation é um desses recursos.
2. O que é uma notação Infix?
O Kotlin permite que algumas funções sejam chamadas sem usar ponto e colchetes. These are called infix methods, and their use can result in code that looks much more like a natural language.
Isso é mais comumente visto na definição deMap em linha:
map(
1 to "one",
2 to "two",
3 to "three"
)
“to” pode parecer uma palavra-chave especial, mas neste exemplo, este é um métodoto() aproveitando a notação infixa e retornando umPair<A, B>.
3. Funções do Infix da Biblioteca Padrão Comum
Além da funçãoto(), usada para criar instânciasPair<A, B>, existem algumas outras funções que são definidas comoinfix.
Por exemplo, as várias classes numéricas -Byte,Short, Int,eLong - todas definem as funções bit a bitand(), or(), shl(), shr(), ushr(),exor(), permitindo algumas expressões mais legíveis:
val color = 0x123456
val red = (color and 0xff0000) shr 16
val green = (color and 0x00ff00) shr 8
val blue = (color and 0x0000ff) shr 0
A classeBoolean define as funções lógicasand(), or()exor() de maneira semelhante:
if ((targetUser.isEnabled and !targetUser.isBlocked) or currentUser.admin) {
// Do something if the current user is an Admin, or the target user is active
}
A classeString também define as funçõesmatchezip como infixos, permitindo alguns códigos simples de ler:
"Hello, World" matches "^Hello".toRegex()
Existem alguns outros exemplos que podem ser encontrados em toda a biblioteca padrão, mas esses são possivelmente os mais comuns.
4. Escrevendo Métodos Infix Personalizados
Freqüentemente, vamos querer escrever nossos próprios métodos de infixo. These can be especially useful, for example, when writing a Domain Specific Language for our application, permitindo que o código DSL seja muito mais legível.
Várias bibliotecas Kotlin já usam isso com grande efeito.
Por exemplo, a bibliotecamockito-kotlin define algumas funções de infixo -doAnswer,doReturn,edoThrow — para uso ao definir o comportamento simulado.
Escrever uma função infixo é um caso simples de seguir três regras:
-
A função é definida em um class ou é um método de extensão para um class
-
A função usa exatamente um parâmetro
-
A função é definida usando a palavra-chaveinfix
Como um exemplo simples, vamos definir uma estruturaAssertion direta para uso em testes. Vamos permitir expressões que podem ser lidas bem da esquerda para a direita usando funções infixas:
class Assertion(private val target: T) {
infix fun isEqualTo(other: T) {
Assert.assertEquals(other, target)
}
infix fun isDifferentFrom(other: T) {
Assert.assertNotEquals(other, target)
}
}
This looks simple and doesn’t seem any different from any other Kotlin code. No entanto, a presença da palavra-chaveinfix nos permite escrever um código como este:
val result = Assertion(5)
result isEqualTo 5 // This passes
result isEqualTo 6 // This fails the assertion
result isDifferentFrom 5 // This also fails the assertion
Imediatamente, isso é mais fácil de ler e mais fácil de entender.
Note that infix functions can also be written as extension methods to existing classes. Isso pode ser poderoso, pois permite aumentar as classes existentes de outros lugares - incluindo a biblioteca padrão - para atender às nossas necessidades.
Por exemplo, vamos adicionar uma função aString para extrair todas as substrings que correspondem a um determinado regex:
infix fun String.substringMatches(r: Regex) : List {
return r.findAll(this)
.map { it.value }
.toList()
}
val matches = "a bc def" substringMatches ".*? ".toRegex()
Assert.assertEquals(listOf("a ", "bc "), matches)
5. Sumário
Este tutorial rápido mostra algumas das coisas que podem ser feitas com funções infix, incluindo como fazer uso de algumas já existentes e como criar nossas próprias para tornar nosso código mais limpo e fácil de ler.
Como sempre, trechos de código podem ser encontrados emover on GitHub.