Reputation: 15824
Is there a way to make something like this work in Kotlin without the reflection?
inline fun <reified T : kotlin.Enum<T>> safeValueOf(type: String?): T? {
return java.lang.Enum.valueOf(T::class.java, type)
}
The example below doesn't compile due to:
Type parameter bound for T in
inline fun <reified T : kotlin.Enum<T>> safeValueOf(type: kotlin.String?): T?
is not satisfied: inferred typeTestEnum?
is not a subtype ofkotlin.Enum<TestEnum?>
enum class TestEnum
fun main() {
val value: TestEnum? = safeValueOf("test")
}
Upvotes: 40
Views: 49688
Reputation: 755
I would typically add something like this to enum:
companion object {
fun from(type: String?): TestEnum = values().find { it.name == type } ?: DEFAULT
}
this would make a clean call
val value = TestEnum.from("test")
of course you can make it return null
Upvotes: 18
Reputation: 47297
Create an extension and then call valueOf<MyEnum>("value")
. If the type is invalid, you'll get null and have to handle it
inline fun <reified T : Enum<T>> valueOf(type: String): T? {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: IllegalArgumentException) {
null
}
}
Alternatively, you can set a default value, calling valueOf<MyEnum>("value", MyEnum.FALLBACK)
, and avoiding a null response. You can extend your specific enum to have the default be automatic
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T {
return try {
java.lang.Enum.valueOf(T::class.java, type)
} catch (e: IllegalArgumentException) {
default
}
}
Or if you want both, make the second:
inline fun <reified T : Enum<T>> valueOf(type: String, default: T): T = valueOf<T>(type) ?: default
Upvotes: 19
Reputation: 2165
Since Kotlin 1.1, it's possible to access the constants in an enum class in a generic way, using the enumValues() and enumValueOf() functions:
enum class RGB { RED, GREEN, BLUE }
inline fun <reified T : Enum<T>> printAllValues() {
print(enumValues<T>().joinToString { it.name })
}
printAllValues<RGB>() // prints RED, GREEN, BLUE
https://kotlinlang.org/docs/reference/enum-classes.html#working-with-enum-constants
Upvotes: 7
Reputation: 97328
Your function works if you specify the type parameter value explicitly:
val value = safeValueOf<TestEnum>("test")
The original code is supposed to work as well, but doesn't work because of a bug in the type inference implementation: https://youtrack.jetbrains.com/issue/KT-11218
Upvotes: 26