How can I use user input to choose element in enum class – Kotlin

I need to get the values ​​of an element from an enum class using user input with the same name as the element. And it’s not working unless I cascade if statements.

I tried to get the element by creating a variable and using it to get the Dir but it didn’t work that way

enum class Dir( val dx: Int = 0, val dy: Int = 0) {
    UP(0, -1), Down(0, 1), Left(-1,0), Right(1,0)
}

fun main(){
    val choice = readln()
    println(Dir.choice)
}

I expected to get the following result:

user input: Up

(0, -1)

user input: Down

(0, 1)

>Solution :

There are several ways to do this. One of them is to use the built-in valueOf() function of the enum, that returns the Dir value with the name matching the string that you pass to valueOf:

Dir.valueOf("Down") == Dir.Down

But that is a bit brittle depending on where you get the input from. If during a refactoring you decide to rename a constant, you might break some user inputs.

A very neat example of that is the typo you made in the value UP (which is full uppercase). If you were to rename it to Up, users that input UP will start failing.

So you could instead add a property to your enum to represent the external name you expect, and write a function to find the enum value based on this external name:

enum class Dir(
    val cliName: String,
    val dx: Int = 0,
    val dy: Int = 0,
) {
    UP("up", 0, -1),
    Down("down", 0, 1),
    Left("left", -1, 0),
    Right("right", 1, 0);

    companion object {
        private valuesByCliName = values().associateBy { it.cliName }

        fun fromCliName(name: String): Dir = valuesByCliName[name]
            ?: throw IllegalArgumentException("Unknown direction '$name'")
    }
}

Leave a Reply