我需要将字符串转换为Enum值,但是想要一个如果字符串不是枚举则返回null的函数。
enum class Colors{
Red, Green, Blue
}
我可以使用Colors.valueOf(testString),只要testString是value,但是如果它无效,就会出现异常,在这种情况下我希望为null。
因为我经常需要这样做,所以扩展功能将是理想的选择。但是扩展名需要对Colors类进行操作,而不是对Colors类型的对象进行操作。
任何人都知道如何编写这样的扩展名吗?理想情况下,对于任何枚举类都是通用的。
编写顶层函数很简单,但是我正在寻找一个充当标准“方法”的函数
// instead of
val willGetAnException = Colors.valueOf("Yellow") // standard existing fun
val willGetNull = Colors.valueOrNullOf("Orange") // new fun i seek
理想情况下,它是通用的并且适用于任何枚举
答案 0 :(得分:3)
Colors.values().find { it.name == "Yellow" }
答案 1 :(得分:2)
您不需要扩展名,因为必须在现有对象上调用它们。您需要一个顶级功能。有一个内置的,您可以使用:
/**
* Returns an enum entry with specified name.
*/
@SinceKotlin("1.1")
public inline fun <reified T : Enum<T>> enumValueOf(name: String): T
您可以通过推断类型或明确地调用它:
val a : MyEnumClass = enumValueOf("A")
val b = enumValueOf<MyEnumClass>("B")
但是此方法不可为空:它将java.lang.IllegalArgumentException
抛出未知值。
但是很容易模仿它的行为,并使其具有顶级功能,可用于可为空的枚举:
inline fun <reified T : Enum<*>> enumValueOrNull(name: String): T? =
T::class.java.enumConstants.firstOrNull { it.name == name }
答案 2 :(得分:2)
U可以使用类似这样的东西:
inline fun <reified T : Enum<T>> String.asEnumOrDefault(defaultValue: T? = null): T? =
enumValues<T>().firstOrNull { it.name.equals(this, ignoreCase = true) } ?: defaultValue
然后:"Yellow".asEnumOrDefault(Colors.Green)
答案 3 :(得分:0)
鉴于在Kotlin中安全地访问Enum值并不容易,所以我发布了一个enum-or-null-kt库来提供速记函数集合,使您可以编写如下代码:
TypeError: array([[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]],
[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]],
[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]],
...,
[[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
...,
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.],
[0., 0., 0., ..., 0., 0., 0.]],
[[0., 0. has type <class 'numpy.ndarray'>, but expected one of: numbers.Real
有了它,您不仅可以使用名称访问Enum值,而且可以将任意高阶函数作为谓词子句传递。当您需要处理自定义转换(例如JPA属性转换器)时,这很方便。
答案 4 :(得分:0)
Kotlin API 不能通过简单地使用 <reified T: Enum<T>>
来工作。它抛出类型为 InvocationTargetException
的异常。所以我直接通过参数传递给type: Class<T>
。
private fun <T> enumValueOf(type: Class<T>, enum: String) : T {
return type.enumConstants.first { it.toString() == enum }
}
if (type.isEnum) enumValueOf(#Field.type, value as String)