¿Hay alguna forma de emitir un argumento when a una enumeración?
enum class PaymentStatus(val value: Int) { PAID(1), UNPAID(2) } fun f(x: Int) { val foo = when (x) { PaymentStatus.PAID -> "PAID" PaymentStatus.UNPAID -> "UNPAID" } } El ejemplo anterior no funcionará, ya que x es int y los valores proporcionados son la enumeración, si voy por PaymentStatus.PAID.value , funcionaría, pero no obtendría el beneficio de when (cobertura completa), y
when (x as PaymentStatus)No funciona.
¿Alguien tiene alguna idea para hacer que esto funcione?
Si necesita verificar un valor, puede hacer algo como esto:
fun f(x: Int) { val foo = when (x) { PaymentStatus.PAID.value -> "PAID" PaymentStatus.UNPAID.value -> "UNPAID" else -> throw IllegalStateException() } } O puede create un método de fábrica en el objeto complementario de la clase de enumeración :
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" } }No necesita when en este caso de uso particular.
Dado que su objetivo es obtener el nombre del elemento de enum que tiene un valor específico x , puede iterar sobre los elementos de PaymentStatus de esa manera y elegir el elemento coincidente usando firstOrNull :
fun getStatusWithValue(x: Int) = PaymentStatus.values().firstOrNull { it.value == x }?.toString() println(getStatusWithValue(2)) // "UNPAID" Llamar a toString() en un elemento de enum devolverá su nombre.
Editar: dado que no desea que el código se compile cuando se agrega un nuevo estado de PaymentStatus , puede usar un exhaustivo 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" } }Básicamente depende de cómo desee resolver la identificación del valor de enumeración apropiado. El resto es probablemente bastante fácil.
Aquí hay algunas variantes para resolver eso:
función de extensión a PaymentStatus.Companion (o integre la función en 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 Uso de él en un when :
fun f(x : Int) = when (PaymentStatus.fromValue(x)) { PAID -> "PAID" // or PAID.name() UNPAID -> "unpaid" //... }usando una función genérica para todas sus enumeraciones
inline fun <reified T : Enum<T>> identifyFrom(identifier : (T) -> Boolean) = T::class.java.enumConstants.single(identifier) // or again: singleOrNull ?: throw IllegalArgumentException maybe?entonces con el siguiente uso:
fun f(x : Int) = when (identifyFrom<PaymentStatus> { it.value = x }) { PAID -> "PAID" UNPAID -> "UNPAID" } esta variante claramente tiene la ventaja de que se puede reutilizar básicamente para cualquier enum en la que desee obtener un valor basado en alguna propiedad o propiedades
usando when para identificar la enum apropiada:
fun PaymentStatus.Companion.fromValue(i : Int) = when (i) { 1 -> PAID 2 -> UNPAID else -> IllegalArgumentException("$i is not a valid value for PaymentStatus") } mismo uso que con el primer ejemplo. Sin embargo: no usaría este enfoque a menos que tenga una muy buena razón para hacerlo. La razón por la que no lo usaría: requiere que siempre recuerde adaptar tanto el valor de enumeración como su contraparte correspondiente en la fromValue . Así que siempre tienes que actualizar los valores (al menos) dos veces ;-)