Rangos (Range) y progresiones (Progression) — son un mecanismo incorporado en Kotlin para representar secuencias de valores con un paso determinado. Se utilizan a menudo en la programación de bucles, condiciones, iteración sobre colecciones y validación de datos. Range se introdujo como una forma de hacer que la sintaxis de Kotlin sea más concisa y expresiva en comparación con Java.
En Java, estas tareas se resolvían con bucles for y while utilizando índices — lo cual era prolijo y propenso a errores. En Kotlin, aparecieron operadores compactos para crear rangos (por ejemplo, 1..10) y métodos para definir pasos.
Kotlin proporciona rangos numéricos estándar (IntRange, LongRange, CharRange, UIntRange, etc.) y interfaces para crear progresiones personalizadas:
Ejemplo de código:
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 // Comprobación de valores val x = 42 if (x in 1..100) println("¡En el rango!")
Puedes definir un rango para tus tipos implementando los operadores rangeTo y 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)
Características clave:
start..end, downTo, step).in, !in).¿Qué devuelve la expresión 1..5 realmente?
Crea una instancia de la clase IntRange, que implementa la interfaz ClosedRange<Int>. No es una colección, sino un objeto que define límites y pasos. Implementación perezosa.
¿Por qué el paso (step) de Range siempre es 1? ¿Cómo se puede cambiar el paso?
Por defecto, el paso de un rango es 1 (o -1 para downTo). Para un paso diferente se utilizan los métodos step y downTo. Por ejemplo:
for (i in 2..10 step 2) println(i)
¿Se pueden usar rangos con tipos que no implementan Comparable?
No, para que funcionen correctamente los rangos personalizados, el tipo debe implementar la interfaz Comparable, de lo contrario, el operador rangeTo será imposible.
step.El desarrollador utiliza el bucle for (i in 5..1) sin downTo, esperando que impima "5, 4, 3, 2, 1", pero al final el bucle no se ejecuta ni una vez.
Pros:
Contras:
Uso de progresiones con downTo y step para iterar sobre informes con el intervalo requerido, haciendo que el código sea compacto y auto-documentado.
Pros:
Contras: