ProgrammingKotlin開発者、バックエンド開発者

Kotlinにおける数値範囲(RangeおよびProgression)メカニズムはどのように機能し、独自の範囲を作成するにはどうすればよいか、またそれをどのようなタスクに使用するか?

Hintsage AIアシスタントで面接を突破

回答。

**範囲(Range)および進行(Progression)**は、特定のステップを持つ値のシーケンスを表すためのKotlinの組み込みメカニズムです。これらは、ループ、条件、コレクションの反復、およびデータのバリデーションを扱う際に頻繁に使用されます。Rangeは、Kotlinの構文をJavaに比べてより簡潔で表現力豊かにする方法の1つとして登場しました。

問題の歴史

Javaでは、類似のタスクはforおよびwhileループをインデックスと共に使用して解決されており、冗長でありエラーが発生しやすいものでした。Kotlinでは、範囲を作成するためのコンパクトな演算子(例えば、1..10)やステップを指定するためのメソッドが登場しました。

問題点

  • 値の範囲を簡単に渡す必要があります(例:1から100までのすべての数値)。
  • 反復およびバリデーション時の便利さの向上。
  • ユーザー定義タイプのために範囲をオーバーライドできる可能性。

解決策

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..enddownTostep)。
  • 所属チェック(in!in)の組み込み。
  • ユーザー定義タイプの範囲と進行を定義する機能。

誤解を招く質問。

1..5という式は実際には何を返しますか?

それは、ClosedRange<Int>インターフェースを実装するIntRangeクラスのインスタンスを作成します。これはコレクションではなく、境界とステップを定義するオブジェクトです。遅延実装です。

なぜRangeのステップは常に1ですか?ステップを変更するにはどうすればよいですか?

デフォルトで、範囲のステップは1(またはdownToの場合は-1)です。他のステップを使用するには、stepとdownToメソッドを使用します。例えば:

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

Comparableを実装していない型と範囲を使用できますか?

いいえ、カスタム範囲が正しく機能するためには、型はComparableインターフェースを実装する必要があります。さもなければ、演算子rangeToは機能しません。

タイプエラーおよびアンチパターン

  • stepメソッドを使用せずにRangeのステップを変更しようとする。
  • Comparableを持たない型と範囲を使用する。
  • 方向を混同する(例:5..1は何も返しません)。

実生活の例

ネガティブケース

開発者がdownToなしでforループ(i in 5..1)を使用し、"5, 4, 3, 2, 1"を期待するが、実際にはループは一度も実行されない。

利点:

  • 構文がシンプル。

欠点:

  • 負の範囲の動作が分かりにくい。
  • 初心者が混乱しやすい。

ポジティブケース

適切な間隔を持つレポートを反復処理するためにdownToとstepを使用し、コードをコンパクトで自己文書化させる。

利点:

  • 簡潔なスタイル。
  • 境界を越えるエラーが発生する可能性は低い。

欠点:

  • ステップと方向の特性を知っておく必要がある。