ProgrammazioneSviluppatore Backend

Descrivi il meccanismo degli intervalli numerici in Kotlin: come funzionano Range e Progression, come creare intervalli personalizzati e in quali scenari è conveniente applicarli?

Supera i colloqui con l'assistente IA Hintsage

Risposta

Storia della questione

Fin dall'inizio, in Kotlin sono stati introdotti gli intervalli (Range) per semplificare le operazioni su insiemi di valori sequenziali — questo è ereditato da linguaggi con una sintassi concisa per lavorare con i numeri (ad esempio, Python). Inoltre, il meccanismo Range è stato esteso a Progression, consentendo di specificare il passo di iterazione e supportare diversi tipi di numeri e caratteri.

Problema

L'iterazione su numeri interi, lettere, punti temporali, ecc. richiede spesso una sintassi speciale e un supporto affidabile nella libreria standard, altrimenti il codice diventa ingombrante, illeggibile e soggetto a errori nei confini.

Soluzione

In Kotlin ci sono i tipi standard IntRange, CharRange e LongRange, oltre a Progression per l'iterazione con passo. Inoltre, è possibile definire intervalli per tipi comparabili arbitrari.

// Intervallo semplice for (i in 1..5) print(i) // 12345 // Intervallo con passo for (i in 1..10 step 2) print(i) // 13579 // Intervallo inverso for (i in 5 downTo 1) print(i) // 54321 // Intervallo personalizzato (ad esempio, per Version) data class Version(val major: Int, val minor: Int): Comparable<Version> { override fun compareTo(other: Version): Int = compareValuesBy(this, other, Version::major, Version::minor) } operator fun ClosedRange<Version>.iterator(): Iterator<Version> = object : Iterator<Version> { var current = start override fun hasNext() = current <= endInclusive override fun next() = current.also { current = Version(current.major, current.minor + 1) } } val v1 = Version(1, 0) val v2 = Version(1, 3) for (v in v1..v2) println(v)

Caratteristiche principali:

  • Sintassi standard per gli intervalli: .., downTo, until, step
  • Lavorare con tipi numerici, caratteri e tipi personalizzati
  • Applicazione in cicli, verifica di appartenenza, suddivisioni, validazioni

Domande trabocchetto.

Qual è la differenza tra l'espressione 1..5 e 1 until 5?

1..5 include entrambi gli estremi dell'intervallo: 1,2,3,4,5. 1 until 5 non include l'ultimo elemento: 1,2,3,4.

È possibile definire un intervallo con passo inferiore a zero utilizzando step?

No. Per gli intervalli decrescenti, usa la costruzione downTo, poi step: 5 downTo 1 step 2 (ottieni 5,3,1).

È possibile utilizzare intervalli con tipi che non implementano Comparable?

No. Per creare un intervallo, è necessario che il tipo supporti il confronto. Altrimenti, il compilatore non consentirà la definizione.

Errori tipici e antipattern

  • Utilizzo di until invece di .. o viceversa, confusione con l'inclusione dei confini
  • Definizione di un passo negativo per un intervallo crescente (step non rende l'intervallo inverso)
  • Mancato rispetto dei requisiti di Comparable per i tipi personalizzati nell'intervallo

Esempio dalla vita reale

Caso negativo

Nel codice, invece di 1 until n+1 è stato utilizzato 1..n. Otteniamo un elemento in più, il ciclo esce dai limiti consentiti.

Pro:

  • Cattura involontaria del caso limite

Contro:

  • Errori nelle suddivisioni, calcoli errati delle somme al confine

Caso positivo

Si utilizza for (i in 0 until n) per indicizzare un array di lunghezza n, l'intervallo corrisponde esattamente ai valori consentiti degli indici.

Pro:

  • Esclusi gli errori di accesso all'array
  • Maggiore leggibilità

Contro:

  • È necessario ricordare la differenza tra .. e until quando si passa tra linguaggi