Az enum osztályok számos okból sok vitát váltanak ki az Android világában, mégis nap mint nap bizonyítják, hogy tapasztalt fejlesztők használják őket. Miért van ez így?
(Figyelem: bár a kód szintaxisa itt Kotlin nyelven lesz, minden itt leírt információ érvényes a Java enum osztályokra is)
Mi az Enum osztály?
Egyszerűen fogalmazva, az Enum egy speciális osztálytípus, amely konstansok listáját tartalmazza. Leggyakrabban egy adott objektum különböző típusainak ábrázolására használják, vagy amikor egy változó csak egy bizonyos értékkészlet egyikét adhatja meg.
enum class Direction { NORTH, SOUTH, EAST, WEST}
Az enum konstansok nem feltétlenül igényelnek értéket. Érték nélkül if- és switch utasításokon keresztül érvényesítésben használhatók.
val directionToTreasure = Direction.NORTHwhen(directionToTreasure) { Direction.NORTH -> indicateNorth() Direction.SOUTH -> indicateSouth() Direction.EAST -> indicateEast() Direction.WEST -> indicateWest()}
Vélhetően nem a legjobb módja ezeknek a jelzőfüggvényeknek a kezelésének, de érted a lényeget. Legalábbis nagyon szórakoztató lesz
A használatuk azonban kiterjeszthető az egyes konstansokhoz csatolt értékekkel.
enum class Color(val rgb: Int) { RED(0xFF0000) GREEN(0x00FF00) BLUE(0x0000FF)}
Ha így használjuk az enum osztályokat, akkor az értéküket így kaphatjuk meg:
val shirtColour = Color.BLUEval color: Int = shirtColour.rgb
Mit tud még egy enum?
Röviden összefoglalva, kurva sokat
Először is, konstansok helyett az enumokat anonim osztályok is megvalósíthatják saját metódusaikkal és az alapmetódusok felülírásával.
enum class ProtocolState yadayada {}
Az interfészeket is megvalósíthatják hasonló módon
enum class IntArithmetics yadayada {}
Végül az enumnak van két konstansa, amelyek néhány elég hasznos értéket szolgáltatnak.
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}
Sőt, ezen konstansok használatának köszönhetően kényelmesen leképezhetjük az enum és a String/Int típusok között is.
Enum -> Int
yourEnum.ordinal
Int -> Enum
EnumType.values()
String -> Enum
EnumType.valueOf(yourString)
Enum -> String
yourEnum.name
Kredit a StackOverflow-n ennek a srácnak a leképezés megosztásáért
Mi a célja az Enum osztályoknak?
Megértelek, nem a legegyszerűbb dolog, de azért felvilágosítalak.
Az enum osztályokat többnyire arra használják, hogy olvashatóbb kódot készítsenek. Amikor van egy objektumod, amelynek több különböző típusa is lehet, sokkal tömörebb azonosítani őket egy olvasható értékkel, mint valami tetszőleges egész számmal.
// 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()}
Az enumok másik hasznos célja az, amikor olyan adatod van, amely stringként érkezik, de végül int értékre kell leképezned, például amikor az API megadja az objektumod típusát, de át kell adnod egy RecyclerView adapterbe, amely Int-et igényel a View típusokhoz. Én személy szerint ezt a módszert használtam az enum osztályomban, hogy ez megtörténjen.
@JvmStaticfun getType(type: String): BlockType? = when(type) { "hero" -> ContentHero "products" -> ContentProductList else -> null }
Miért nem szabad Enum osztályokat használni
Valószínűleg most arra gondolsz, hogy “Várj egy kicsit. Mindent elmondtál az Enum osztályok használatáról, most meg azt mondod, hogy ne használjam őket?”. Hallgass meg, haver.
Egyszerűen fogalmazva, az Enums drága, haver! Tudom, hogy a mobiltelefonok napról napra jobbak, de egyrészt még mindig túl sokan vannak a kevésbé erős telefonokkal, másrészt az alkalmazások készítésének módja és az általunk használt könyvtárak is több memóriát használnak.
Ez már régi hír. Az enumok memóriaproblémát jelentenének a Dalvikkal futó telefonoknál, de azt alapvetően megszüntették az ART (Android Runtime Machine) helyett. Ha hozzávesszük, hogy még a szegényebb országokban élő embereknek is elég erős telefonjaik vannak, és hogy a Proguard ma már jobban tudja optimalizálni a kódot, mint valaha, akkor nyugodtan kijelenthetjük, hogy az Enums már nem okoz problémát a teljesítményben.
Még mindig van néhány alternatíva, amit használhatsz, amivel hasonló eredményeket érhetsz el, mint egy Enum osztály.
Constants
A konstansok is szuper tömörek. Egyetlen értéket tárolnak és nevet adnak neki. Emellett rendkívül könnyűek.
*Def
A *Def annotáció szintén nagyszerű, ha van egy olyan változód, amely csak bizonyos értékeket vesz fel.
@IntDef({RED, GREEN, BLUE})
Miért választod még mindig az enumokat ezekkel az alternatívákkal szemben?
Ahol az enum sokkal jobban csillog, mint funkcionális testvérei, az a kimeríthetőség. Ha Kotlinnal használod, használhatsz egy switch utasítást, mint ez
val foo = when(someEnum) {}
És amikor ezt teszed, kénytelen vagy kezelni egy esetet az enum minden konstansához, különben a kódod nem fog lefordítani. Állandókkal és *def megjegyzésekkel a legjobb, amit kapsz, lint figyelmeztetések. Az enumok egyszerűen biztonságosabb kódhoz vezetnek.
(Credits to u/-manabreak from Reddit for this)
Szóval, amíg az enumok használata tömörebb kódot eredményez az alkalmazásod számára, és különösen a Kotlin esetében, jobb esetbiztonságot, addig mindenképpen enumerálj a szíved szerint.