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)
CodePudding user response:
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'")
}
}