ProgrammierungKotlin-Entwickler, Backend-Entwickler

Wie funktioniert der Mechanismus von Zahlenbereichen (Range und Progression) in Kotlin, wie erstellt man eigene Bereiche und für welche Aufgaben werden sie verwendet?

Bestehen Sie Vorstellungsgespräche mit dem Hintsage-KI-Assistenten

Antwort.

Bereiche (Range) und Progressionen (Progression) sind ein integriertes Mittel in Kotlin zur Darstellung von Wertfolgen mit einem bestimmten Schritt. Sie werden häufig bei der Arbeit mit Schleifen, Bedingungen, der Iteration über Sammlungen und der Validierung von Daten eingesetzt. Range wurde als einer der Wege eingeführt, um die Syntax von Kotlin im Vergleich zu Java kürzer und ausdrucksvoller zu gestalten.

Geschichte der Frage

In Java wurden ähnliche Aufgaben über Schleifen wie for und while mit Indizes gelöst – umständlich und fehleranfällig. In Kotlin gibt es kompakte Operatoren zur Erstellung von Bereichen (zum Beispiel, 1..10) und Methoden zur Festlegung von Schritten.

Problem

  • Notwendigkeit, einen Bereich von Werten einfach zu übergeben (zum Beispiel, alle numerischen Werte von 1 bis 100).
  • Erhöhung des Komforts bei der Iteration und Validierung.
  • Möglichkeit, Bereiche für benutzerdefinierte Typen zu überschreiben.

Lösung

Kotlin bietet Standardzahlenbereiche (IntRange, LongRange, CharRange, UIntRange usw.) und Schnittstellen zur Erstellung eigener Progressionen:

Beispielcode:

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 // Wertprüfung val x = 42 if (x in 1..100) println("Im Bereich!")

Benutzerdefinierte Bereiche

Man kann einen Bereich für die eigenen Typen definieren, indem man die Operatoren rangeTo und Progression implementiert:

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)

Schlüsselmerkmale:

  • Kompakte Syntax zur Erstellung von Bereichen (start..end, downTo, step).
  • Integrierte Mitgliedschaftsprüfungen (in, !in).
  • Möglichkeit, Bereiche und Progressionen für benutzerdefinierte Typen zu definieren.

Fangfragen.

Was gibt der Ausdruck 1..5 tatsächlich zurück?

Er erstellt eine Instanz der Klasse IntRange, die das Interface ClosedRange<Int> implementiert. Das ist keine Sammlung, sondern ein Objekt, das die Grenzen und den Schritt definiert. Lazy-Implementierung.

Warum beträgt der Schritt (step) bei Range immer 1? Wie kann man den Schritt ändern?

Standardmäßig beträgt der Schritt für den Bereich 1 (oder -1 bei downTo). Für einen anderen Schritt werden die Methoden step und downTo verwendet. Zum Beispiel:

for (i in 2..10 step 2) println(i)

Kann man Bereiche mit Typen verwenden, die nicht Comparable implementieren?

Nein, für die korrekte Funktionsweise eines benutzerdefinierten Bereichs muss der Typ das Interface Comparable implementieren, sonst ist der Operator rangeTo nicht möglich.

Typische Fehler und Anti-Patterns

  • Versuch, den Schritt bei Range ohne die Methode step zu ändern.
  • Verwendung von Bereichen mit Typen ohne Comparable.
  • Verwechslung der Richtung (zum Beispiel gibt 5..1 nichts aus).

Beispiel aus dem Leben

Negativer Fall

Ein Entwickler verwendet eine Schleife for (i in 5..1) ohne downTo und erwartet, dass sie "5, 4, 3, 2, 1" ausgibt, aber die Schleife wird kein einziges Mal ausgeführt.

Vorteile:

  • Einfache Syntax.

Nachteile:

  • Unklare Funktionsweise eines negativen Bereichs.
  • Leicht verwirrend für Anfänger.

Positiver Fall

Einsatz von Progressionen mit downTo und step zur Iteration über Berichte mit dem gewünschten Intervall, wodurch der Code kompakt und selbstdokumentierend wird.

Vorteile:

  • Prägnanter Stil.
  • Geringe Wahrscheinlichkeit für Grenzübertritte.

Nachteile:

  • Man muss die Besonderheiten von Schritten und Richtungen kennen.