Sidebar

Klasy enum wzbudzają wiele kontrowersji w świecie Androida z wielu powodów, ale wciąż okazują się być używane przez doświadczonych programistów dzień po dniu. Dlaczego tak jest?

(Głowy do góry: podczas gdy składnia kodu tutaj będzie w Kotlinie, wszystkie informacje tutaj zawarte odnoszą się również do klas enum w Javie)

Co to jest klasa Enum?

Najprościej mówiąc, Enum jest specjalnym typem klasy, który przechowuje listę stałych. Najczęstszym zastosowaniem tego typu jest reprezentowanie różnych typów jednego konkretnego obiektu, lub gdy zmienna może być tylko jedną z pewnego zestawu wartości.

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

Stałe enum niekoniecznie wymagają wartości. Bez wartości mogą być używane w walidacji poprzez instrukcje ifs i switch.

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

Prawdopodobnie nie jest to najlepszy sposób na obsługę tych funkcji wskazujących, ale masz pomysł. Przynajmniej będzie dużo zabawy

Jego użycie może być jednak rozszerzone o wartości dołączone do każdej stałej.

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

Gdy używasz klas enum w ten sposób, możesz uzyskać ich wartość tak:

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

Co jeszcze może zrobić Enum?

Ujmując to w skrócie, cholernie dużo

Po pierwsze, zamiast stałych, enumy mogą być zaimplementowanymi anonimowymi klasami z własnymi metodami i nadrzędnymi metodami bazowymi.

enum class ProtocolState yadayada {}

Mogą również implementować interfejsy w podobny sposób

enum class IntArithmetics yadayada {}

Wreszcie, enum ma dwie stałe, które zapewniają ci kilka całkiem użytecznych wartości.

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}

W rzeczywistości, dzięki użyciu tych stałych, można również wygodnie mapować między typami enum i String/Int.

Enum -> Int

yourEnum.ordinal

Int -> Enum

EnumType.values()

String -> Enum

EnumType.valueOf(yourString)

Enum -> String

yourEnum.name

Credits to this guy on StackOverflow for sharing this mapping

Jaki jest cel klas Enum?

Dostaję cię, to nie jest najprostsza rzecz, ale wypełnię cię.

Po większej części, klasy enum są używane do produkcji bardziej czytelnego kodu. Kiedy masz obiekt, który może mieć wiele różnych typów, o wiele bardziej zwięzłe jest identyfikowanie ich za pomocą czytelnej wartości niż jakiejś arbitralnej liczby całkowitej.

// 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()}

Innym użytecznym celem Enum są sytuacje, gdy masz dane, które przychodzą jako ciąg znaków, ale musisz ostatecznie zmapować je do wartości int, jak wtedy, gdy API podaje typ obiektu, ale musisz przekazać go do adaptera RecyclerView, który wymaga Int dla typów widoku. Osobiście użyłem tej metody w mojej klasie enum, aby tak się stało.

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

Dlaczego nie powinieneś używać klas Enum

Założę się, że teraz myślisz „Wstrzymaj się na chwilę. Powiedziałeś mi wszystko o tym, jak używać Enumów, a teraz po prostu powiesz mi, żebym ich nie używał?”. Posłuchaj mnie kolego.

Po prostu, Enumy są drogie kolego! Wiem, że telefony komórkowe stają się coraz lepsze z dnia na dzień, ale po pierwsze, wciąż jest zbyt wielu ludzi z mniej wydajnymi telefonami, a po drugie, sposób w jaki tworzymy aplikacje i biblioteki, których używamy, również zużywają więcej pamięci.

To stara wiadomość. Enumy byłyby problemem z pamięcią dla telefonów działających z Dalvikiem, ale to w zasadzie zostało zaniechane w miejsce ART (Android Runtime Machine). Dodając do tego fakt, że nawet ludzie w biedniejszych krajach mają dość potężne telefony, i że Proguard może teraz optymalizować kod lepiej niż kiedykolwiek, można bezpiecznie powiedzieć, że Enumy nie powodują już problemu z wydajnością.

Jest jeszcze kilka alternatyw, których można użyć, aby osiągnąć podobne wyniki do klasy Enum.

Stałe

Stałe są również super zwięzłe. Przechowują pojedynczą wartość i nadają jej nazwę. Są również niezwykle lekkie.

*Def

Adnotacja *Def jest również świetna, jeśli masz zmienną, która przyjmuje tylko określone wartości.

@IntDef({RED, GREEN, BLUE})

Dlaczego wciąż wybierać enumy nad tymi alternatywami?

Gdzie enum błyszczy znacznie bardziej niż jego funkcjonalne rodzeństwo, jest wyczerpywalność. Kiedy używasz Kotlina, możesz użyć instrukcji switch jak to

val foo = when(someEnum) {}

A kiedy to zrobisz, jesteś zmuszony do obsługi przypadku dla każdej stałej w twoim enum, w przeciwnym razie twój kod nie skompiluje się. Ze stałymi i adnotacjami *def, najlepsze, co otrzymujesz, to ostrzeżenia lint. Enumy po prostu prowadzą do bezpieczniejszego kodu.

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

Więc tak długo, jak twoje użycie enumów prowadzi do bardziej zwięzłego kodu dla twojej aplikacji, a zwłaszcza w przypadku Kotlina, lepszego bezpieczeństwa przypadku, przez wszystkie środki, wyliczaj do woli.

Dodaj komentarz