Can I have an `enum class` with an "other value"? ...
# getting-started
r
Can I have an
enum class
with an "other value"? Aka
Copy code
enum class Status(val value: Int) {
  Present(2),
  Absent(1),
  Error(value)
}
?
j
Do you mean that you would like
Error
to support different values depending on the case?
r
Or rather, all other values. I'm using it for status codes coming from a proprietary jar, so I have a few hints on what might come out of there.
I know these two values, but any others might occur
j
Enums are not meant for that. Each enum value (entry in the list) has only one instance, so you cannot have 2 instances of
Status.Error
with different values. So I would say you have 2 main options: 1. if you don't really need the error code (the
value
property), you may keep an enum but remove the
value
property - just map your error codes to one of the 3 enum states without storing the error code in the enum value. Note that, in Kotlin, enums don't need to be associated with a number or anything - maybe that's the missing piece of the puzzle for you 2. if you do need the code, it means you want different instances of those enum values (with different codes). In that case, you cannot use an enum but you can use a
sealed class
instead
Option 1 could look like this:
Copy code
enum class Status {
    Present,
    Absent,
    Error;

    companion object {
        fun fromStatusCode(code: Int) = when(code) {
            1 -> Absent
            2 -> Present
            else -> Error
        }
    }
}
I'm assuming 1 and 2 here are probably not what you want (assuming you had assigned numbers to the enum entries just because you thought you had to). But you could map your actual status codes here.
I can elaborate on option 2 if that's what you need, but I'll wait for your answer first
r
Kinda got to
Copy code
sealed class CardStatus(val value: Int) {}
class CardPresent() : CardStatus(2)
class CardAbsent(): CardStatus(1)
class CardError(value: Int): CardStatus(value)
fun Int.toCardStatus(): CardStatus {
    return when(this) {
        (2) -> CardPresent()
        (1) -> CardAbsent()
        else -> CardError(this)
    }
}
... slack enter always trips me up -.-
So I can keep the status code around for the error message in the future
companion object would be the more conventional way to go about it?
... switched it over, thanks for the help!
j
companion object would be the more conventional way to go about it?
Not necessarily, but it depends on where you put this extension on
Int
. Because
Int
is a very common type, there is a chance this will pollute auto-completion in your project, hence why I would personally tend to favor
CardStatus.fromCode(Int)
over extensions on
Int
, if this is a public function like in your case. if it's a private function, it's quite ok
2 minor points about your sealed class: 1. Because
CardPresent
and
CardAbsent
always hold the same value, they can be `object`s instead of classes (you don't need new instances every time) 2. If the naming makes sense with nesting, you can nest your sealed class's subclasses inside the sealed class, so they are referred to with the
SealedParent.Child
syntax. In your case, this would read `CardStatus.Present`/`CardStatus.Absent`/`CardStatus.Error` - but that's a matter of taste
r
Does mess a tiny bit with the
toString
in terms of clarity, but then you should add enough context 😄
j
If you care about
toString()
, it may be worth making
CardError
a
data class
then 😉
r
Yup, just did ^^