J'essaie de trouver le meilleur moyen de faire une «recherche inversée» sur un enum à Kotlin. L'un de mes points à retenir de Effective Java était que vous introduisiez une carte statique dans l'énumération pour gérer la recherche inversée. Porter ceci sur Kotlin avec une simple énumération me conduit à un code qui ressemble à ceci:
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]
}
}
}
Ma question est la suivante: est-ce la meilleure façon de procéder ou existe-t-il une meilleure façon de procéder? Que faire si j'ai plusieurs énumérations qui suivent un modèle similaire? Y a-t-il un moyen dans Kotlin de rendre ce code plus réutilisable entre les énumérations?
Réponses:
Tout d'abord, l'argument de
fromInt()
devrait être unInt
, pas unInt?
. Essayer d'obtenir uneType
utilisation de null conduira évidemment à null, et un appelant ne devrait même pas essayer de le faire. LeMap
n'a également aucune raison d'être mutable. Le code peut être réduit à:Ce code est si court que, franchement, je ne suis pas sûr que cela vaille la peine d'essayer de trouver une solution réutilisable.
la source
fromInt
Enum.valueOf(String)
map[type] ?: throw IllegalArgumentException()
by lazy{}
pourmap
etgetOrDefault()
pour un accès plus sûr parvalue
Type.fromInt()
partir du code Java, vous devrez annoter la méthode avec@JvmStatic
.nous pouvons utiliser
find
qui Renvoie le premier élément correspondant au prédicat donné, ou null si aucun élément de ce type n'a été trouvé.la source
first { ... }
place car il ne sert à rien de multiples résultats.first
n'est pas une amélioration car elle modifie le comportement et lanceNoSuchElementException
si l'élément n'est pas trouvé oùfind
ce qui est égal àfirstOrNull
renvoienull
. donc si vous voulez lancer au lieu de renvoyer une utilisation nullefirst
fun valueFrom(valueA: Int, valueB: String): EnumType? = values().find { it.valueA == valueA && it.valueB == valueB }
vous pouvez également lever une exception si les valeurs ne sont pas dans l'énumération:fun valueFrom( ... ) = values().find { ... } ?: throw Exception("any message")
ou vous pouvez l'utiliser lors de l'appel de cette méthode:var enumValue = EnumType.valueFrom(valueA, valueB) ?: throw Exception( ...)
Cela n'a pas beaucoup de sens dans ce cas, mais voici une "extraction logique" pour la solution de @ JBNized:
En général, c'est le problème avec les objets compagnons qu'ils peuvent être réutilisés (contrairement aux membres statiques d'une classe Java)
la source
Une autre option, qui pourrait être considérée comme plus "idiomatique", serait la suivante:
Qui peut ensuite être utilisé comme
Type[type]
.la source
Je me suis retrouvé à faire la recherche inversée par coutume, codé à la main, valeur deux fois et suis venu avec l'approche suivante.
Faites
enum
implémenter une interface partagée:Cette interface (aussi étrange que soit son nom :)) marque une certaine valeur comme code explicite. Le but est de pouvoir écrire:
Ce qui peut être facilement réalisé avec le code suivant:
la source
Une variante de certaines propositions précédentes pourrait être la suivante, en utilisant un champ ordinal et getValue:
}
la source
Un autre exemple de mise en œuvre. Cela définit également la valeur par défaut (ici à
OPEN
) si aucune entrée ne correspond à aucune option enum:}
la source
Est venu avec une solution plus générique
Exemple d'utilisation:
la source
True Idiomatic Kotlin Way. Sans code de réflexion gonflé:
la source
val t = Type.values () [ordinal]
:)
la source