Котлин: Использование перечислений с когда - PullRequest
0 голосов
/ 24 января 2019

Есть ли способ привести аргумент 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, а предоставленные значения - это enum, если я пойду на PaymentStatus.PAID.value, это сработает, но тогда я не получу преимущества, когда (полное покрытие) и

when (x as PaymentStatus)

не работает.

У кого-нибудь есть идеи сделать эту работу?

Ответы [ 3 ]

0 голосов
/ 24 января 2019

Вам не нужно when в данном конкретном случае использования.

Поскольку ваша цель - получить имя элемента enum, имеющего определенное значение x, вы можете перебрать элементы PaymentStatus и подобрать соответствующий элемент, используя firstOrNull:

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

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

Вызов toString() для элемента enum вернет его имя.

0 голосов
/ 25 января 2019

Это в основном зависит от того, как вы хотите решить идентификацию соответствующего значения перечисления.Остальное, вероятно, достаточно просто.

Вот несколько вариантов решения этой проблемы:

  1. функция расширения до 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" //...
    }
    
  2. с использованием универсальной функции для всех ваших перечислений

    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, где вы хотите получить значение на основе какого-либо свойства или свойств

  3. с использованием when для определения соответствующего enum:

    fun PaymentStatus.Companion.fromValue(i : Int) = when (i) {
      1 -> PAID
      2 -> UNPAID
      else -> IllegalArgumentException("$i is not a valid value for PaymentStatus")
    }
    

    того же использования, что и в первом примере.Тем не менее: я бы не использовал этот подход, если только у вас нет для этого веских причин.Причина, по которой я не стал бы его использовать: он требует, чтобы вы всегда помнили адаптировать и значение enum, и его соответствующий аналог в функции fromValue.Таким образом, вы всегда должны обновить значения (как минимум) дважды; -)

0 голосов
/ 24 января 2019

Если вам нужно проверить значение, вы можете сделать что-то вроде этого:

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

        else -> throw IllegalStateException()
    }
}

Или вы можете создать фабричный метод create в объекте-компаньоне из enum класс:

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"
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...