1. 序章

前回の記事では、 Kotlin で範囲を作成する方法と、 Int、Long Charタイプを反復処理するのがいかに簡単かを示しました。

しかし、カスタムタイプ反復したい場合はどうでしょうか。 出来ますか? 答えはイエスです! それでは、コードに飛び込んでその方法を見てみましょう。

2. カラフルなタイプ

RGBカラーを表す単純なクラスがあると想像してみましょう。

class CustomColor(val rgb: Int): Comparable<CustomColor> {}

RGBカラーの範囲で反復できると便利です。

val a = CustomColor(0x000000)
val b = CustomColor(0xCCCCCC)
for (cc in a..b) {
   // do things
}

3. IntRangeの概要

簡単に言えば、 Comparable、Iterable、およびClosedRangeを実装する必要があります。 以前の記事から、Comparableを実装する必要があることはすでにわかっています。

他の2つのインターフェースについては、いくつかのヒントについてIntRangeクラス宣言を詳しく見ていきましょう。

public class IntRange(start: Int, endInclusive: Int) : 
  IntProgression(start, endInclusive, 1), ClosedRange<Int> 

その後、 IntProgression の宣言は、それが実装していることを示しています反復可能 :

public open class IntProgression : Iterable<Int>

したがって、これを機能させるために同様のことを実行したいと思います。

4. ColorRangeクラス

IntRange と同様に、ColorRangeクラスを作成しましょう。

ここでは、 IntProgression、の模倣もスキップします。これは、デフォルトのステップが1であっても問題ないためです。これにより、作業が少し簡素化され、単純に[ X183X]ClosedRangeとIterableの両方を直接実装する:

class ColorRange(override val start: CustomColor,
  override val endInclusive: CustomColor) : ClosedRange<CustomColor>, Iterable<CustomColor>{

    override fun iterator(): Iterator<CustomColor> {
        return ColorIterator(start, endInclusive)
    }
}

iterator()の実装では、 ColorIteratorクラスを返します。このクラスは、実際に範囲をステップスルーするという手間のかかる作業を行います。

なぜなら ColorRange を実装します ClosedRange >> インターフェイス、実装する必要があります compareTo 上の方法 CustomColor クラス:

override fun compareTo(other: CustomColor): Int {
    return this.rgb.compareTo(other.rgb)
}

5. ColorIteratorクラス

ColorIteratorはパズルの最後のピースです:

class ColorIterator(val start: CustomColor, val endInclusive: CustomColor) : Iterator<CustomColor> {

    var initValue = start

    override fun hasNext(): Boolean {
        return initValue <= endInclusive
    }

    override fun next(): CustomColor {
        return initValue++
    }
}

ご了承ください initValue タイプです CustomColor。 だから、それを変異させるには ++ 演算子、追加する必要があります inc() 方法 CustomColor 同じように:

operator fun inc(): CustomColor {
    return CustomColor(rgb + 1)
}

6. カスタム範囲の使用

もうすぐ着きます!

カスタム範囲を定義しているため、CustomColorクラスはrangeToメソッドを実装する必要があります。 rangeToメソッドを使用すると、..を使用して範囲を反復処理できます。 オペレーター 、追加する方法のようなもの株式会社使用することができます ++ オペレーター。

最終製品をチェックしてみましょう:

class CustomColor(val rgb: Int): Comparable<CustomColor> {

    override fun compareTo(other: CustomColor): Int {
        return this.rgb.compareTo(other.rgb)
    }

    operator fun rangeTo(that: CustomColor) = ColorRange(this,that)

    operator fun inc(): CustomColor {
        return CustomColor(rgb + 1)
    }
}

そして、それが私たちに必要なすべてです!

最後に、 CustomColorクラスの範囲を使用して、これらすべてがどのように連携するかを見てみましょう。

@Test
fun assertHas10Colors(){
    assertTrue {
        val a = CustomColor(1)
        val b = CustomColor(10)
        val range = a..b
        for (cc in range) {
            println(cc)
        }
        range.toList().size == 10
    }
}

このテストでは、 range 変数を定義し、 CustomColor オブジェクトを反復処理し、それをリストに変換するために使用しました。

範囲で標準のcontainsメソッドを使用する別の例を見てみましょう。

@Test
fun assertContains0xCCCCCC(){
    assertTrue {
        val a = CustomColor(0xBBBBBB)
        val b = CustomColor(0xDDDDDD)
        val range = a..b
        range.contains(CustomColor(0xCCCCCC))
    }
}

7. 結論

Kotlinには、 Int、Long 、およびChar値の範囲のネイティブ実装があります。 この記事では、カスタムクラスに範囲を実装する方法を学びました。

いつものように、コードはGitHub利用できます。