Sivupalkki

Enum-luokat herättävät paljon keskustelua Android-maailmassa monista syistä, mutta kokeneet kehittäjät käyttävät niitä silti päivittäin. Miksi näin on?

(Heads up: vaikka koodin syntaksi tässä on Kotlin, kaikki tässä olevat tiedot pätevät myös Java-enum-luokkiin)

Mikä on Enum-luokka?

Lyhyesti sanottuna Enum on erityinen luokkatyyppi, joka pitää sisällään listan vakioita. Yleisin käyttötapa on edustaa yhden tietyn objektin eri tyyppejä tai kun muuttuja voi olla vain yksi tietystä joukosta arvoja.

enum class Direction { NORTH, SOUTH, EAST, WEST}

Enumin vakiot eivät välttämättä vaadi arvoa. Ilman arvoa niitä voidaan käyttää validoinnissa if- ja switch-lausekkeiden avulla.

val directionToTreasure = Direction.NORTHwhen(directionToTreasure) { Direction.NORTH -> indicateNorth() Direction.SOUTH -> indicateSouth() Direction.EAST -> indicateEast() Direction.WEST -> indicateWest()}

Ei varmaankaan paras tapa käsitellä näitä osoittavat funktioita, mutta ymmärrät idean. Ainakin siitä tulee paljon hauskaa

Sen käyttöä voidaan kuitenkin laajentaa siten, että kuhunkin vakioon liitetään arvo.

enum class Color(val rgb: Int) { RED(0xFF0000) GREEN(0x00FF00) BLUE(0x0000FF)}

Kun käytät enum-luokkia tällä tavalla, voit saada niiden arvon näin:

val shirtColour = Color.BLUEval color: Int = shirtColour.rgb

Mitä muuta enumilla voi tehdä?

Lyhyesti sanottuna helvetin paljon

Ensimmäiseksi, vakioiden sijaan enumit voidaan toteuttaa anonyymeinä luokkina, joilla on omat metodinsa ja jotka voivat ohittaa perusmetodit.

enum class ProtocolState yadayada {}

Näillä luokilla voidaan myös toteuttaa rajapintoja vastaavalla tavalla

enum class IntArithmetics yadayada {}

Loppujen lopuksi enumilla on kaksi vakiota, jotka tuottavat sinulle joitain melko hyödyllisiä arvoja.

val name: String // The name of the constantval ordinal: Int // The position of the constant in the list of valuesif (shirtColour.name == "BLUE") { // Do some blue stuff}

Tosiasiassa näiden vakioiden käytön ansiosta voit myös kätevästi kartoittaa enum- ja String/Int-tyyppien välillä.

Enum -> Int

yourEnum.ordinal

Int -> Enum

EnumType.values()

String -> Enum

EnumType.valueOf(yourString)

Enum -> String

yourEnum.name

Krediitit tälle kaverille StackOverflow’ssa, joka on jakanut tämän mappauksen

Mitä tarkoitusta varten Enum-luokkia käytetään?

Minä ymmärrän, että se ei ole kaikkein suoraviivaisin asia, mutta selitän sinulle.

Enum-luokkia käytetään suurimmaksi osaksi luettavamman koodin tuottamiseen. Kun sinulla on objekti, jolla voi olla useita eri tyyppejä, on paljon ytimekkäämpää tunnistaa ne luettavalla arvolla kuin jollakin mielivaltaisella kokonaisluvulla.

// Bad codewhen(direction) { 0 -> goNorth() 1 -> goSouth() 2 -> goEast() 3 -> goWest()}// Good codewhen(direction) { Direction.NORTH -> goNorth() Direction.SOUTH -> goSouth() Direction.EAST -> goEast() Direction.WEST -> goWest()}

Enumien toinen hyödyllinen käyttötarkoitus on silloin, kun sinulla on dataa, joka tulee sisään merkkijonona, mutta sinun täytyy lopulta kartoittaa se int-arvoksi, kuten silloin, kun API antaa objektin tyypin, mutta sinun täytyy välittää se RecyclerView-sovittimeen, joka vaatii Int:n View-tyypeille. Itse käytin tätä metodia enum-luokassani saadakseni tämän tapahtumaan.

@JvmStaticfun getType(type: String): BlockType? = when(type) { "hero" -> ContentHero "products" -> ContentProductList else -> null }

Miksi sinun ei pitäisi käyttää enum-luokkia

Lasken vetoa, että ajattelet nyt: ”Odota hetki. Kerroit minulle kaiken siitä, miten Enum-luokkia käytetään, ja nyt aiot vain kieltää minua käyttämästä niitä?”. Kuuntele minua, kaveri.

Yksinkertaisesti sanottuna, Enumit ovat kalliita, kaveri! Tiedän, että matkapuhelimet paranevat päivä päivältä, mutta ensinnäkin on vielä liikaa ihmisiä, joilla on vähemmän tehokkaat puhelimet ja toiseksi tapa, jolla teemme sovelluksia ja käyttämämme kirjastot käyttävät myös enemmän muistia.

Tämä on vanha uutinen. Enumit olisivat muistiongelma puhelimissa, jotka toimivat Dalvikilla, mutta se on periaatteessa lopetettu ART:n (Android Runtime Machine) tilalle. Kun tähän lisätään se tosiasia, että jopa köyhemmissä maissa asuvilla ihmisillä on melko tehokkaita puhelimia ja että Proguard osaa nykyään optimoida koodia paremmin kuin koskaan, on turvallista sanoa, että Enumit eivät enää aiheuta ongelmaa suorituskyvyssä.

On vielä muutama vaihtoehto, joita voit käyttää ja joilla voit saavuttaa samanlaisia tuloksia kuin Enum-luokalla.

Konstantit

Konstantit ovat myös supertiiviitä. Ne pitävät sisällään yhden arvon ja antavat sille nimen. Ne ovat myös erittäin kevyitä.

*Def

*Def-merkintä on myös loistava, jos sinulla on muuttuja, joka ottaa vastaan vain tiettyjä arvoja.

@IntDef({RED, GREEN, BLUE})

Miksi silti valita Enumit näiden vaihtoehtojen sijasta?

Missä Enum loistaa paljon enemmän kuin funktionaaliset sisaruksensa, on tyhjentävyys. Kotlinin kanssa käytettynä voit käyttää switch-lauseketta esimerkiksi näin

val foo = when(someEnum) {}

Ja kun teet niin, sinun on pakko käsitellä tapaus jokaiselle enumin vakiolle, muuten koodisi ei käänny. Kun käytät vakioita ja *def-merkintöjä, saat parhaimmillaan lint-varoituksia. Enumit yksinkertaisesti johtavat turvallisempaan koodiin.

(Credits to u/-manabreak from Reddit for this)

Niin kauan kuin enumien käyttö johtaa tiiviimpään koodiin sovelluksessasi ja erityisesti Kotlinin tapauksessa parempaan tapauskohtaiseen turvallisuuteen, kaikin mokomin, luettele sydämesi kyllyydestä.

Jätä kommentti