Een Kotlin Range Iterator maken op een aangepast object

1. Inleiding

In een vorig artikel hebben we laten zien hoe we een bereik in Kotlin kunnen maken, en hoe gemakkelijk het is om dit te herhalen Int, Long en Char types.

Maar wat als we dat willen itereren over een aangepast type? Is het mogelijk? Het antwoord is ja! Dus laten we in de code springen en kijken hoe.

2. Een kleurrijk type

Laten we ons voorstellen dat we een eenvoudige klasse hebben die een RGB-kleur vertegenwoordigt:

class CustomColor (val rgb: Int): Vergelijkbaar {} 

Het zou leuk zijn om te kunnen herhalen over een reeks RGB-kleuren:

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

3. Een snelle blik in IntRange

Simpel gezegd, we zullen moeten implementeren Vergelijkbaar, Herhaalbaar, en Gesloten bereik. Uit ons vorige artikel weten we al dat we het moeten implementeren Vergelijkbaar.

Laten we voor de andere twee interfaces een duik nemen in het IntRange class declaratie voor enkele hints:

openbare klasse IntRange (start: Int, endInclusive: Int): IntProgression (start, endInclusive, 1), ClosedRange 

En dan, IntProgressieUit de verklaring blijkt dat het implementeert Herhaalbaar:

openbare open klasse IntProgression: Iterable

Dus we willen iets soortgelijks doen om dit te laten werken.

4. Kleurbereik Klasse

Leuk vinden IntRange, laten we een Kleurbereik klasse.

Voor onze doeleinden zullen we nabootsen overslaan IntProgressie, ook sinds we zijn oké met een standaardstap van 1. Dit vereenvoudigt de zaken een beetje en stelt ons in staat om eenvoudig te doen beide implementeren Gesloten bereik en Herhaalbaar direct:

class ColorRange (override waarde start: CustomColor, override val endInclusive: CustomColor): ClosedRange, Iterable {override fun iterator (): Iterator {return ColorIterator (start, endInclusive)}}

Voor onze implementatie van iterator (), we zullen een ColorIterator klasse die het zware werk zal doen om daadwerkelijk door het bereik te stappen.

Omdat Kleurbereik implementeert het Gesloten bereik interface, moeten we de vergelijk met methode op Aangepaste kleur klasse:

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

5. ColorIterator Klasse

ColorIterator is het laatste stuk van de puzzel:

class ColorIterator (val start: CustomColor, val endInclusive: CustomColor): Iterator {var initValue = start override fun hasNext (): Boolean {return initValue <= endInclusive} override fun next (): CustomColor {return initValue ++}}

Let daar op initValue is van het type Aangepaste kleur. Dus om het te muteren met de ++ operator, moeten we de inc () methode om Aangepaste kleur ook:

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

6. Gebruik van het aangepaste bereik

We zijn er bijna!

Omdat we ons aangepaste assortiment definiëren, Aangepaste kleur class moet de bereikNaar methode. De bereikNaar methode stelt ons in staat om ons bereik te herhalen met behulp van de .. operator, een beetje zoals toevoegen inc stelt ons in staat om de ++ operator.

Laten we het eindproduct eens bekijken:

class CustomColor (val rgb: Int): Vergelijkbaar {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)}}

En dat is alles wat we nodig hebben!

Laten we tot slot eens kijken hoe dit allemaal samenwerkt, door met behulp van een reeks van onze Aangepaste kleur klasse:

@Test fun assertHas10Colors () {assertTrue {val a = CustomColor (1) val b = CustomColor (10) val bereik = a..b voor (cc in bereik) {println (cc)} bereik.toList (). Size = = 10}}

In deze test hebben we een bereik variabele en wordt gebruikt om door de Aangepaste kleur objecten, en transformeer het in een lijst.

Laten we nog een voorbeeld bekijken van het gebruik van de standaard bevat methode op het bereik:

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

7. Conclusie

Kotlin heeft een native implementatie van bereik voor Int, Long en Char waarden. In dit artikel hebben we geleerd hoe we een bereik in een aangepaste klasse kunnen implementeren.

Zoals altijd is de code beschikbaar op GitHub.