Kotlin:在 when 中使用枚举
Kotlin: Using enums with when
有没有办法将 when 参数转换为枚举?
enum class PaymentStatus(val value: Int) {
PAID(1),
UNPAID(2)
}
fun f(x: Int) {
val foo = when (x) {
PaymentStatus.PAID -> "PAID"
PaymentStatus.UNPAID -> "UNPAID"
}
}
上面的例子不会工作,因为 x 是 int 并且提供的值是枚举,如果我按照 PaymentStatus.PAID.value
它会工作但是我没有得到什么时候的好处(完全覆盖), 和
when (x as PaymentStatus)
无效。
任何人有任何想法使这项工作?
如果你需要检查一个值,你可以这样做:
fun f(x: Int) {
val foo = when (x) {
PaymentStatus.PAID.value -> "PAID"
PaymentStatus.UNPAID.value -> "UNPAID"
else -> throw IllegalStateException()
}
}
或者您可以在 enum 的 伴随对象 中创建工厂方法 create
class:
enum class PaymentStatus(val value: Int) {
PAID(1),
UNPAID(2);
companion object {
fun create(x: Int): PaymentStatus {
return when (x) {
1 -> PAID
2 -> UNPAID
else -> throw IllegalStateException()
}
}
}
}
fun f(x: Int) {
val foo = when (PaymentStatus.create(x)) {
PaymentStatus.PAID -> "PAID"
PaymentStatus.UNPAID -> "UNPAID"
}
}
在此特定用例中,您不需要 when
。
由于您的目标是获取具有特定值 x
的 enum
元素的名称,您可以像这样遍历 PaymentStatus
的元素并选择匹配的元素使用 firstOrNull
:
fun getStatusWithValue(x: Int) = PaymentStatus.values().firstOrNull {
it.value == x
}?.toString()
println(getStatusWithValue(2)) // "UNPAID"
在 enum
元素上调用 toString()
将 return 它的名称。
编辑: 由于您不想在添加新的 PaymentStatus
时编译代码,因此您可以使用详尽的 when
:
fun paymentStatusNumToString(x: Int): String {
val status = PaymentStatus.values().first { it.value == x }
// when must be exhaustive here, because we don't use an else branch
return when(status) {
PaymentStatus.PAID -> "PAID" // you could use status.toString() here too
PaymentStatus.UNPAID -> "UNPAID"
}
}
这基本上取决于你想如何解决合适的枚举值的识别。剩下的可能很简单。
这里有一些变体可以解决这个问题:
对PaymentStatus.Companion
的扩展功能(或将功能集成到PaymentStatus.Companion
):
fun PaymentStatus.Companion.fromValue(i : Int) = PaymentStatus.values().single { it.value = i } // or if you want another fallback, just use singleOrNull and add ?: with an appropriate default value
它在 when
中的用法:
fun f(x : Int) = when (PaymentStatus.fromValue(x)) {
PAID -> "PAID" // or PAID.name()
UNPAID -> "unpaid" //...
}
对所有枚举使用通用函数
inline fun <reified T : Enum<T>> identifyFrom(identifier : (T) -> Boolean) = T::class.java.enumConstants.single(identifier) // or again: singleOrNull ?: throw IllegalArgumentException maybe?
然后使用以下用法:
fun f(x : Int) = when (identifyFrom<PaymentStatus> { it.value = x }) {
PAID -> "PAID"
UNPAID -> "UNPAID"
}
这个变体显然有一个好处,它可以重复用于基本上任何 enum
,你想根据某些 属性 或属性
[=44= 获得值]
使用 when
来识别合适的 enum
:
fun PaymentStatus.Companion.fromValue(i : Int) = when (i) {
1 -> PAID
2 -> UNPAID
else -> IllegalArgumentException("$i is not a valid value for PaymentStatus")
}
与第一个示例相同的用法。但是:除非您有充分的理由,否则我不会使用这种方法。我不使用它的原因是:它要求您始终记住要适应枚举值及其在 fromValue
函数中对应的值。所以你总是必须更新值(至少)两次 ;-)
将 when
与 enum
一起使用的可能解决方法如下(也许它不会完全针对该问题,但我认为将其作为参考是个好主意):
package com.company.my_package
import com.company.my_package.MyEnum.*
enum class MyEnum {
ENUM_ITEM_1,
ENUM_ITEM_2,
ENUM_ITEM_3
}
val myCommand1 = { input: Any? -> input.toString() }
val myCommand2 = { input: Any? -> input.toString() }
val myCommand3 = { input: Any? -> input.toString() }
val myElseCommand = { input: Any? -> input.toString() }
fun main() {
val myValue = null
when {
ENUM_ITEM_1 == myValue -> myCommand1(myValue)
ENUM_ITEM_2 == myValue -> myCommand2(myValue)
ENUM_ITEM_3 == myValue -> myCommand3(myValue)
else -> myElseCommand(myValue)
}
}
有没有办法将 when 参数转换为枚举?
enum class PaymentStatus(val value: Int) {
PAID(1),
UNPAID(2)
}
fun f(x: Int) {
val foo = when (x) {
PaymentStatus.PAID -> "PAID"
PaymentStatus.UNPAID -> "UNPAID"
}
}
上面的例子不会工作,因为 x 是 int 并且提供的值是枚举,如果我按照 PaymentStatus.PAID.value
它会工作但是我没有得到什么时候的好处(完全覆盖), 和
when (x as PaymentStatus)
无效。
任何人有任何想法使这项工作?
如果你需要检查一个值,你可以这样做:
fun f(x: Int) {
val foo = when (x) {
PaymentStatus.PAID.value -> "PAID"
PaymentStatus.UNPAID.value -> "UNPAID"
else -> throw IllegalStateException()
}
}
或者您可以在 enum 的 伴随对象 中创建工厂方法 create
class:
enum class PaymentStatus(val value: Int) {
PAID(1),
UNPAID(2);
companion object {
fun create(x: Int): PaymentStatus {
return when (x) {
1 -> PAID
2 -> UNPAID
else -> throw IllegalStateException()
}
}
}
}
fun f(x: Int) {
val foo = when (PaymentStatus.create(x)) {
PaymentStatus.PAID -> "PAID"
PaymentStatus.UNPAID -> "UNPAID"
}
}
在此特定用例中,您不需要 when
。
由于您的目标是获取具有特定值 x
的 enum
元素的名称,您可以像这样遍历 PaymentStatus
的元素并选择匹配的元素使用 firstOrNull
:
fun getStatusWithValue(x: Int) = PaymentStatus.values().firstOrNull {
it.value == x
}?.toString()
println(getStatusWithValue(2)) // "UNPAID"
在 enum
元素上调用 toString()
将 return 它的名称。
编辑: 由于您不想在添加新的 PaymentStatus
时编译代码,因此您可以使用详尽的 when
:
fun paymentStatusNumToString(x: Int): String {
val status = PaymentStatus.values().first { it.value == x }
// when must be exhaustive here, because we don't use an else branch
return when(status) {
PaymentStatus.PAID -> "PAID" // you could use status.toString() here too
PaymentStatus.UNPAID -> "UNPAID"
}
}
这基本上取决于你想如何解决合适的枚举值的识别。剩下的可能很简单。
这里有一些变体可以解决这个问题:
对
PaymentStatus.Companion
的扩展功能(或将功能集成到PaymentStatus.Companion
):fun PaymentStatus.Companion.fromValue(i : Int) = PaymentStatus.values().single { it.value = i } // or if you want another fallback, just use singleOrNull and add ?: with an appropriate default value
它在
when
中的用法:fun f(x : Int) = when (PaymentStatus.fromValue(x)) { PAID -> "PAID" // or PAID.name() UNPAID -> "unpaid" //... }
对所有枚举使用通用函数
inline fun <reified T : Enum<T>> identifyFrom(identifier : (T) -> Boolean) = T::class.java.enumConstants.single(identifier) // or again: singleOrNull ?: throw IllegalArgumentException maybe?
然后使用以下用法:
fun f(x : Int) = when (identifyFrom<PaymentStatus> { it.value = x }) { PAID -> "PAID" UNPAID -> "UNPAID" }
这个变体显然有一个好处,它可以重复用于基本上任何
[=44= 获得值]enum
,你想根据某些 属性 或属性使用
when
来识别合适的enum
:fun PaymentStatus.Companion.fromValue(i : Int) = when (i) { 1 -> PAID 2 -> UNPAID else -> IllegalArgumentException("$i is not a valid value for PaymentStatus") }
与第一个示例相同的用法。但是:除非您有充分的理由,否则我不会使用这种方法。我不使用它的原因是:它要求您始终记住要适应枚举值及其在
fromValue
函数中对应的值。所以你总是必须更新值(至少)两次 ;-)
将 when
与 enum
一起使用的可能解决方法如下(也许它不会完全针对该问题,但我认为将其作为参考是个好主意):
package com.company.my_package
import com.company.my_package.MyEnum.*
enum class MyEnum {
ENUM_ITEM_1,
ENUM_ITEM_2,
ENUM_ITEM_3
}
val myCommand1 = { input: Any? -> input.toString() }
val myCommand2 = { input: Any? -> input.toString() }
val myCommand3 = { input: Any? -> input.toString() }
val myElseCommand = { input: Any? -> input.toString() }
fun main() {
val myValue = null
when {
ENUM_ITEM_1 == myValue -> myCommand1(myValue)
ENUM_ITEM_2 == myValue -> myCommand2(myValue)
ENUM_ITEM_3 == myValue -> myCommand3(myValue)
else -> myElseCommand(myValue)
}
}