Диапазоны (Range) и прогрессии (Progression) — это встроенный механизм в Kotlin для представления последовательностей значений с определённым шагом. Они часто применяются при работе с циклами, условиями, перебором коллекций и валидацией данных. Range появилась как один из способов сделать синтаксис Kotlin лаконичнее и выразительнее по сравнению с Java.
В Java подобные задачи решались через циклы for и while с индексами — многословно и подвержено ошибкам. В Kotlin появились компактные операторы создания диапазонов (например, 1..10) и методы для задания шагов.
Kotlin предоставляет стандартные числовые диапазоны (IntRange, LongRange, CharRange, UIntRange, и т.д.) и интерфейсы для создания собственных прогрессий:
Пример кода:
for (i in 1..5) print("$i ") // 1 2 3 4 5 for (i in 5 downTo 1 step 2) print("$i ") // 5 3 1 // Проверка значения val x = 42 if (x in 1..100) println("В диапазоне!")
Можно определить диапазон для своих типов, реализовав операторы rangeTo и Progression:
data class Version(val major: Int, val minor: Int) : Comparable<Version> { override fun compareTo(other: Version) = compareValuesBy(this, other, Version::major, Version::minor) } operator fun Version.rangeTo(other: Version) = VersionRange(this, other) class VersionRange( override val start: Version, override val endInclusive: Version ) : ClosedRange<Version> for (v in Version(1, 0)..Version(1, 2)) println(v)
Ключевые особенности:
start..end, downTo, step).in, !in).Что возвращает выражение 1..5 на самом деле?
Оно создает экземпляр класса IntRange, реализующего интерфейс ClosedRange<Int>. Это не коллекция, а объект, определяющий границы и шаг. Lazy-реализация.
Почему шаг (step) у Range всегда 1? Как изменить шаг?
По умолчанию step у диапазона равен 1 (или -1 при downTo). Для иного шага используются методы step и downTo. Например:
for (i in 2..10 step 2) println(i)
Можно ли использовать диапазоны с типами, не реализующими Comparable?
Нет, для корректной работы пользовательского диапазона тип обязан реализовывать интерфейс Comparable, иначе оператор rangeTo будет невозможен.
step.Разработчик использует цикл for (i in 5..1) без downTo, ожидая, что будет "5, 4, 3, 2, 1", а в итоге цикл ни разу не выполнится.
Плюсы:
Минусы:
Использование прогрессии с downTo и step для перебора отчётов с нужным интервалом, делая код компактным и самодокументируемым.
Плюсы:
Минусы: