Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 544 Vote(s) - 3.4 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Kotlin: Using enums with when

#1
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?



Reply

#2
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"
}
}
Reply

#3
It basically depends on how you want to solve the identification of the appropriate enum value. The rest is probably easy enough.

Here are some variants to solve that:

1. extension function to `PaymentStatus.Companion` (or integrate the function into the `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

Usage of it in a `when`:

fun f(x : Int) = when (PaymentStatus.fromValue(x)) {
PAID -> "PAID" // or PAID.name()
UNPAID -> "unpaid" //...
}

1. using a generic function for all your enums

inline fun <reified T : Enum<T>> identifyFrom(identifier : (T) -> Boolean) = T::class.java.enumConstants.single(identifier) // or again: singleOrNull ?: throw IllegalArgumentException maybe?

with the following usage then:

fun f(x : Int) = when (identifyFrom<PaymentStatus> { it.value = x }) {
PAID -> "PAID"
UNPAID -> "UNPAID"
}

this variant clearly has the benefit that it can be reused for basically any `enum` where you want to get a value based on some property or properties

1. using `when` to identify the appropriate `enum`:


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


same usage as with the first example. However: I wouldn't use this approach except you have a really good reason for it. The reason I wouldn't use it: it requires you to always remember to adapt both, the enum value and its corresponding counterpart in the `fromValue`-function. So you always have to update the values (at least) twice ;-)
Reply

#4
A possible workaround to use `when` with an `enum` is the following (maybe it will not target the question entirely but I think is a good idea to have it here as a reference):


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)
}
}
Reply

#5
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"
}
}
Reply

#6
**define your enum**

enum class Images {
ID_PHOTO, PROFILE_IMAGE, IBAN_IMAGE, LICENSE_IMAGE
}
**define object from your enum**

lateinit var selectedImage: Images
**use selectedImage object from your enum with when**

when (selectedImage) {
Images.ID_PHOTO -> binding.idPhoto.setImageURI(uri)
Images.PROFILE_IMAGE -> binding.profileImage.setImageURI(uri)
Images.LICENSE_IMAGE -> binding.licenseImage.setImageURI(uri)
Images.IBAN_IMAGE -> binding.ibanImage.setImageURI(uri)

}

**set value for object**

private fun pickImageFromGallery(image: Images) {
selectedImage = image

}

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through