Ich versuche, den besten Weg zu finden, um eine Enum-Suche in einer Aufzählung in Kotlin durchzuführen. Eine meiner Erkenntnisse aus Effective Java war, dass Sie eine statische Karte in die Enumeration einführen, um die umgekehrte Suche durchzuführen. Wenn ich dies mit einer einfachen Aufzählung nach Kotlin portiere, komme ich zu Code, der so aussieht:
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]
}
}
}
Meine Frage ist, ist dies der beste Weg, oder gibt es einen besseren Weg? Was ist, wenn ich mehrere Aufzählungen habe, die einem ähnlichen Muster folgen? Gibt es in Kotlin eine Möglichkeit, diesen Code über Aufzählungen hinweg wiederverwendbarer zu machen?
Antworten:
Zuallererst sollte das Argument von
fromInt()
ein seinInt
, nicht einInt?
. Der Versuch, eineType
using-Null zu erhalten, führt offensichtlich zu null, und ein Anrufer sollte dies nicht einmal versuchen. DasMap
hat auch keinen Grund, veränderlich zu sein. Der Code kann reduziert werden auf:Dieser Code ist so kurz, dass ich ehrlich gesagt nicht sicher bin, ob es sich lohnt, eine wiederverwendbare Lösung zu finden.
quelle
fromInt
Rückgabe ungleich Null machen wieEnum.valueOf(String)
:map[type] ?: throw IllegalArgumentException()
by lazy{}
für denmap
undgetOrDefault()
für einen sichereren Zugriff vonvalue
Type.fromInt()
Sie die Methode mit Anmerkungen versehen müssen, um aus Java-Code aufrufen zu können@JvmStatic
.Wir können verwenden,
find
welches das erste Element zurückgibt, das mit dem angegebenen Prädikat übereinstimmt, oder null, wenn kein solches Element gefunden wurde.quelle
first { ... }
stattdessen die Verwendung, da mehrere Ergebnisse nicht verwendet werden können.first
ist keine Verbesserung, da sie das Verhalten ändert und auslöst,NoSuchElementException
wenn das Element nicht dort gefunden wird, wo esfind
derfirstOrNull
Rückgabe entsprichtnull
.first
fun valueFrom(valueA: Int, valueB: String): EnumType? = values().find { it.valueA == valueA && it.valueB == valueB }
Sie können auch eine Ausnahme auslösen, wenn die Werte nicht in der Aufzählung enthalten sind:fun valueFrom( ... ) = values().find { ... } ?: throw Exception("any message")
oder Sie können sie verwenden, wenn Sie diese Methode aufrufen:var enumValue = EnumType.valueFrom(valueA, valueB) ?: throw Exception( ...)
In diesem Fall macht es nicht viel Sinn, aber hier ist eine "Logikextraktion" für die Lösung von @ JBNized:
Im Allgemeinen ist dies die Sache bei Begleitobjekten, die wiederverwendet werden können (im Gegensatz zu statischen Elementen in einer Java-Klasse).
quelle
Eine andere Option, die als "idiomatischer" angesehen werden könnte, wäre die folgende:
Welches kann dann wie verwendet werden
Type[type]
.quelle
Ich fand mich dabei wieder, die umgekehrte Suche durch benutzerdefinierte, handcodierte Werte einige Male durchzuführen, und fand den folgenden Ansatz.
Lassen Sie
enum
s eine gemeinsame Schnittstelle implementieren:Diese Schnittstelle (wie seltsam der Name auch sein mag :)) markiert einen bestimmten Wert als expliziten Code. Das Ziel ist es, schreiben zu können:
Was mit dem folgenden Code leicht erreicht werden kann:
quelle
Eine Variante einiger früherer Vorschläge könnte die folgende sein, wobei Ordnungsfeld und getValue verwendet werden:
}}
quelle
Eine weitere Beispielimplementierung. Dies setzt auch den Standardwert (hier auf
OPEN
), wenn nein, die Eingabe stimmt mit keiner Aufzählungsoption überein:}}
quelle
Hat eine allgemeinere Lösung gefunden
Anwendungsbeispiel:
quelle
True Idiomatic Kotlin Way. Ohne aufgeblähten Reflexionscode:
quelle
val t = Type.values () [ordinal]
:) :)
quelle