Próbuję znaleźć najlepszy sposób na „wyszukiwanie wsteczne” wyliczenia w Kotlinie. Jednym z moich wniosków z Effective Java było wprowadzenie statycznej mapy do wyliczenia w celu obsługi wyszukiwania wstecznego. Przeniesienie tego do Kotlina za pomocą prostego wyliczenia prowadzi mnie do kodu, który wygląda następująco:
enum class Type(val value: Int) {
A(1),
B(2),
C(3);
companion object {
val map: MutableMap<Int, Type> = HashMap()
init {
for (i in Type.values()) {
map[i.value] = i
}
}
fun fromInt(type: Int?): Type? {
return map[type]
}
}
}
Moje pytanie brzmi: czy to najlepszy sposób, czy jest lepszy sposób? A co, jeśli mam kilka wyliczeń, które mają podobny wzór? Czy w Kotlinie jest sposób, aby ten kod był bardziej nadający się do ponownego wykorzystania w wyliczeniach?
Odpowiedzi:
Przede wszystkim argument
fromInt()
powinien być anInt
, a nieInt?
. Próba uzyskaniaType
using null oczywiście prowadzi do null, a dzwoniący nie powinien nawet próbować tego robić. NieMap
ma również powodu, aby być zmiennym. Kod można zredukować do:Ten kod jest tak krótki, że, szczerze mówiąc, nie jestem pewien, czy warto szukać rozwiązania wielokrotnego użytku.
źródło
fromInt
zwrot nie jest zerowy, jakEnum.valueOf(String)
:map[type] ?: throw IllegalArgumentException()
by lazy{}
domap
igetOrDefault()
dla bezpieczniejszego dostępu przezvalue
Type.fromInt()
z kodu Java, musisz dodać adnotację do metody@JvmStatic
.możemy użyć
find
which Zwraca pierwszy element pasujący do danego predykatu lub null, jeśli takiego elementu nie znaleziono.źródło
first { ... }
Zamiast tego używane jest oczywiste ulepszenie, ponieważ nie ma potrzeby uzyskiwania wielu wyników.first
nie jest ulepszeniem, ponieważ zmienia zachowanie i wyrzuca,NoSuchElementException
jeśli element nie zostanie znaleziony, gdziefind
jest równyfirstOrNull
zwrotowinull
. więc jeśli chcesz rzucić zamiast zwracać null użyjfirst
fun valueFrom(valueA: Int, valueB: String): EnumType? = values().find { it.valueA == valueA && it.valueB == valueB }
Możesz również zgłosić wyjątek, jeśli wartości nie ma w wyliczeniu:fun valueFrom( ... ) = values().find { ... } ?: throw Exception("any message")
lub możesz go użyć podczas wywoływania tej metody:var enumValue = EnumType.valueFrom(valueA, valueB) ?: throw Exception( ...)
W tym przypadku nie ma to większego sensu, ale oto „wyodrębnianie logiki” dla rozwiązania @ JBNized:
Ogólnie rzecz biorąc, chodzi o obiekty towarzyszące, które można ponownie wykorzystać (w przeciwieństwie do statycznych elementów członkowskich w klasie Java)
źródło
Inna opcja, którą można by uznać za bardziej „idiomatyczną”, byłaby następująca:
Które można następnie wykorzystać jak
Type[type]
.źródło
Znalazłem się kilka razy, wykonując wyszukiwanie wsteczne przez niestandardowe, ręcznie kodowane, wartości i wymyśliłem następujące podejście.
Make
enum
s implementuje wspólny interfejs:Ten interfejs (jakkolwiek dziwna nazwa to :)) oznacza określoną wartość jako jawny kod. Celem jest umiejętność pisania:
Co można łatwo osiągnąć za pomocą następującego kodu:
źródło
Wariantem niektórych poprzednich propozycji może być następujący, wykorzystujący pole porządkowe i getValue:
}
źródło
Kolejna przykładowa realizacja. Spowoduje to również ustawienie wartości domyślnej (tutaj na
OPEN
), jeśli żadne dane wejściowe nie pasują do żadnej opcji wyliczenia:}
źródło
Pojawił się z bardziej ogólnym rozwiązaniem
Przykładowe użycie:
źródło
True Idiomatic Kotlin Way. Bez nadętego kodu odbicia:
źródło
Nieco rozszerzone podejście do przyjętego rozwiązania z funkcją sprawdzania wartości null i wywołania
źródło
val t = Type.values () [porządkowa]
:)
źródło