1. Введение
Kotlin - это язык, который добавляет множество новых функций, позволяющих писать более чистый и удобный для чтения код.
Это, в свою очередь, значительно упрощает обслуживание нашего кода и обеспечивает лучший конечный результат нашей разработки. Инфиксная нотация - одна из таких функций.
2. Что такое инфиксная нотация?
Kotlin позволяет вызывать некоторые функции без использования точки и скобок. Они называются инфиксными методами, и их использование может привести к созданию кода, который гораздо больше похож на естественный язык.
Чаще всего это можно увидеть в определении онлайн-карты:
map(
1 to "one",
2 to "two",
3 to "three"
)
“to” может выглядеть как специальное ключевое слово, но в данном примере это метод to(), использующий инфиксную запись и возвращающий пару<A, B>.
3. Общие инфиксные функции стандартной библиотеки
Помимо функции to(), используемой для создания пары экземпляров<A, B>, существуют некоторые другие функции, которые определяются как инфиксные.
Например, различные числовые классы – Byte, Short, Int и Long – определяют побитовые функции and(), or(), shl(), shr(), ushr() и xor(), что позволяет использовать некоторые более удобочитаемые выражения:
val color = 0x123456
val red = (color and 0xff0000) shr 16
val green = (color and 0x00ff00) shr 8
val blue = (color and 0x0000ff) shr 0
Класс Boolean определяет логические функции and(), or() и xor() аналогичным образом:
if ((targetUser.isEnabled and !targetUser.isBlocked) or currentUser.admin) {
// Do something if the current user is an Admin, or the target user is active
}
Класс String также определяет функции match и zip как инфиксные, что позволяет использовать некоторый простой для чтения код:
"Hello, World" matches "^Hello".toRegex()
Есть несколько других примеров, которые можно найти в стандартной библиотеке, но они, возможно, наиболее распространенные.
4. Написание пользовательских инфиксных методов
Часто нам захочется написать свои собственные инфиксные методы. Они могут быть особенно полезны, например, при написании языка, специфичного для предметной области, для нашего приложения, что позволяет сделать код DSL более читабельным.
Несколько библиотек Kotlin уже используют это с большим успехом.
Например, библиотека mockito-kotlin определяет некоторые инфиксные функции — doAnswer, doReturn и doThrow — для использования при определении макетного поведения.
Написание инфиксной функции - это простой случай следования трем правилам:
- Функция либо определена в классе, либо является методом расширения для класса
- Функция принимает только один параметр
- Функция определяется с помощью ключевого слова infix
В качестве простого примера давайте определим простую структуру утверждений для использования в тестах. Мы собираемся разрешить выражения, которые легко читаются слева направо, используя инфиксные функции:
class Assertion<T>(private val target: T) {
infix fun isEqualTo(other: T) {
Assert.assertEquals(other, target)
}
infix fun isDifferentFrom(other: T) {
Assert.assertNotEquals(other, target)
}
}
Это выглядит просто и ничем не отличается от любого другого кода на Kotlin. Однако наличие ключевого слова infix позволяет нам писать такой код:
val result = Assertion(5)
result isEqualTo 5 // This passes
result isEqualTo 6 // This fails the assertion
result isDifferentFrom 5 // This also fails the assertion
Это сразу же упрощает чтение и понимание.
Обратите внимание, что инфиксные функции также могут быть записаны как методы расширения существующих классов. Это может быть полезным, поскольку позволяет нам дополнять существующие классы из других источников, включая стандартную библиотеку, в соответствии с нашими потребностями.
Например, давайте добавим к строке функцию, которая извлекает все подстроки, соответствующие заданному регулярному выражению:
infix fun String.substringMatches(r: Regex) : List<String> {
return r.findAll(this)
.map { it.value }
.toList()
}
val matches = "a bc def" substringMatches ".*? ".toRegex()
Assert.assertEquals(listOf("a ", "bc "), matches)
5. Краткое содержание
В этом кратком руководстве показаны некоторые вещи, которые можно сделать с помощью инфиксных функций, в том числе как использовать некоторые существующие и как создать свои собственные, чтобы сделать наш код более понятным и легко читаемым.
Оригинал статьи: https://www.baeldung.com/kotlin/infix-functions