Enum-klasser väcker mycket kontroverser i Android-världen av olika anledningar, men de används fortfarande dagligen av erfarna utvecklare. Varför är det så?
(Heads up: även om syntaxen i koden här kommer att vara i Kotlin, gäller all information här även för Java enum-klasser)
Vad är en Enum-klass?
Simpelt uttryckt är en Enum en speciell klasstyp som innehåller en lista med konstanter. Den vanligaste användningen av detta är att representera olika typer av ett visst objekt, eller när en variabel bara kan vara ett av en viss uppsättning värden.
enum class Direction { NORTH, SOUTH, EAST, WEST}
Konstanterna i en enum kräver inte nödvändigtvis ett värde. Utan ett värde kan de användas vid validering genom ifs- och switch-satser.
val directionToTreasure = Direction.NORTHwhen(directionToTreasure) { Direction.NORTH -> indicateNorth() Direction.SOUTH -> indicateSouth() Direction.EAST -> indicateEast() Direction.WEST -> indicateWest()}
Det är förmodligen inte det bästa sättet att hantera dessa indikeringsfunktioner, men du får en uppfattning. Det blir i alla fall mycket roligt
Der kan dock utvidgas till att inkludera värden som är knutna till varje konstant.
enum class Color(val rgb: Int) { RED(0xFF0000) GREEN(0x00FF00) BLUE(0x0000FF)}
När du använder enum-klasser på det här sättet kan du få fram deras värde på följande sätt:
val shirtColour = Color.BLUEval color: Int = shirtColour.rgb
Vad mer kan en Enum göra?
För att sammanfatta det i ett nötskal, en jävla massa
För det första kan enum istället för konstanter implementeras som anonyma klasser med egna metoder och överordnande av basmetoder.
enum class ProtocolState yadayada {}
De kan också implementera gränssnitt på ett liknande sätt
enum class IntArithmetics yadayada {}
Finalt sett har enum två konstanter som ger dig några ganska användbara värden.
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}
Genom användningen av dessa konstanter kan du faktiskt också enkelt mappa mellan enum- och String/Int-typer.
Enum -> Int
yourEnum.ordinal
Int -> Enum
EnumType.values()
String -> Enum
EnumType.valueOf(yourString)
Enum -> String
yourEnum.name
Krediterar den här killen på StackOverflow för att ha delat med sig av denna mappning
Vad är syftet med Enum-klasser?
Jag förstår att det inte är det mest okomplicerade, men jag ska förklara det för dig.
För det mesta används enum-klasser för att producera mer lättläst kod. När du har ett objekt som kan ha flera olika typer är det mycket mer kortfattat att identifiera dem med ett läsbart värde än ett godtyckligt heltal.
// 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()}
Ett annat användbart syfte med Enums är när du har data som kommer in som en sträng, men du behöver så småningom mappa den till ett int-värde, som när ditt API ger ditt objekts typ, men du måste skicka den till en RecyclerView Adapter som kräver en Int för View-typer. Jag personligen använde den här metoden i min enum-klass för att få det att hända.
@JvmStaticfun getType(type: String): BlockType? = when(type) { "hero" -> ContentHero "products" -> ContentProductList else -> null }
Varför du inte bör använda Enum-klasser
Jag slår vad om att du nu tänker ”Vänta lite. Du berättade allt om hur man använder Enums och nu ska du bara säga att jag inte ska använda dem?”. Lyssna på mig.
Simpelt uttryckt, Enums är dyra! Jag vet att mobiltelefoner blir bättre för varje dag, men för det första finns det fortfarande för många människor där ute med mindre kraftfulla telefoner och för det andra använder det sätt på vilket vi gör appar och de bibliotek vi använder mer minne också.
Detta är gamla nyheter. Enums skulle vara ett minnesproblem för telefoner som körs med Dalvik, men det har i princip upphört och ersatts av ART (Android Runtime Machine). Tillsammans med det faktum att även människor i fattigare länder har ganska kraftfulla telefoner och att Proguard nu kan optimera koden bättre än någonsin kan man lugnt säga att Enums inte längre orsakar något prestandaproblem.
Det finns fortfarande några alternativ som du kan använda och som kan uppnå liknande resultat som en Enum-klass.
Constants
Constants är också superkoncisa. De håller ett enda värde och ger det ett namn. De är också extremt lätta.
*Def
Anteckningen *Def är också bra om du har en variabel som bara tar emot vissa värden.
@IntDef({RED, GREEN, BLUE})
Varför väljer du fortfarande Enums framför dessa alternativ?
Där Enum glänser mycket mer än sina funktionella syskon är uttömmande. När du använder Kotlin kan du använda ett switch-statement som detta
val foo = when(someEnum) {}
Och när du gör det är du tvungen att hantera ett fall för varje konstant i din enum, annars kommer din kod inte att kompileras. Med konstanter och *def-annotationer får du som bäst lint-varningar. Enums leder helt enkelt till säkrare kod.
(Credits to u/-manabreak from Reddit for this)
Så länge din användning av enums leder till mer kortfattad kod för din applikation och särskilt i Kotlins fall, bättre case safety, så kan du för all del enumera till ditt hjärta.