Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin: Using enums with when

Is there any way to cast a when argument to an enum?

 enum class PaymentStatus(val value: Int) {
     PAID(1),
     UNPAID(2) 
 }

fun f(x: Int) {
   val foo = when (x) {
     PaymentStatus.PAID -> "PAID"
     PaymentStatus.UNPAID -> "UNPAID"
   }
}

The above example will not work, as x is int and the values provided are the enum, if I go by PaymentStatus.PAID.value it would work but then I don't get the benefit of when (full coverage), and

when (x as PaymentStatus)

does not work.

Any one have any ideas to make this work?

like image 544
serhan Avatar asked Jan 23 '19 21:01

serhan


2 Answers

If you need to check a value you can do something like this:

fun f(x: Int) {
    val foo = when (x) {
        PaymentStatus.PAID.value -> "PAID"
        PaymentStatus.UNPAID.value -> "UNPAID"

        else -> throw IllegalStateException()
    }
}

Or you can create factory method create in the companion object of enum 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"
    }
}
like image 154
Sergey Avatar answered Nov 11 '22 07:11

Sergey


You don't need when in this particular use-case.

Since your goal is to get the name of the enum element having a specific value x, you can iterate over the elements of PaymentStatus like that and pick the matching element using firstOrNull:

fun getStatusWithValue(x: Int) = PaymentStatus.values().firstOrNull {
     it.value == x
}?.toString()

println(getStatusWithValue(2)) // "UNPAID"

Calling toString() on an enum element will return its name.

Edit: Since you don't want the code to compile when a new PaymentStatus is added, you can just use an exhaustive 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"
  }
}
like image 4
Willi Mentzel Avatar answered Nov 11 '22 07:11

Willi Mentzel