Kotlin Enum Classes
Enum classes
An enum class is declared by adding enum before the class keyword.
Each enum constant is an object, and enum constants are separated with commas.
enum class Direction {
NORTH, SOUTH, WEST, EAST
}
fun main() {
println(Direction.NORTH)
}
Output:
NORTH
Each enum is an instance of the enum class, so it can be initialized with specific values.
enum class Color(val strRgb: String, val hexaRgb: Int) {
RED("#f00", 0xFF0000),
GREEN("#0f0", 0x00FF00),
BLUE("#00f",0x0000FF ),
}
fun main() {
println(Color.RED)
println(Color.RED.name)
println(Color.RED.strRgb)
println(Color.RED.hexaRgb.toString(16))
}
Output:
RED
RED
#f00
ff0000
enum definition format
- An enum can be defined with the
enumkeyword. - The first constant value of a defined enum is set from 0, and each following value increases by 1 from the previous constant value.
- To set irregular values as constant values, add parentheses (
()) next to the constant name and specify the desired integer constant value inside. - If you declare a variable with
valto the right of the enum name, you can check the constant value of that enum element. Theordinaltype can be specified through type declaration.
Reasons to use enum
- It prevents instance creation and inheritance, and guarantees type safety for constant values.
- The most basic reason to use enum classes is to implement type-safe enums.
- Code becomes simpler and easier to read.
Anonymous classes
Enum constants can declare their own anonymous classes and methods, and can override base methods.
enum class ProtocolState {
WAITING {
override fun signal() = TALKING
},
TALKING {
override fun signal() = WAITING
};
abstract fun signal(): ProtocolState
}
fun main() {
println(ProtocolState.TALKING.signal())
println(ProtocolState.WAITING.signal())
}
Output:
WAITING
TALKING
When defining members in an enum class, member definitions and enum constant definitions must be separated with a semicolon (;).
Enum entries cannot have nested classes.
Implementing interfaces in enum classes
An enum class uses interfaces instead of inheritance.
An interface can have one interface member for all entries, or each entry inside an anonymous class can have its own interface implementation.
import java.util.function.BinaryOperator
import java.util.function.IntBinaryOperator
enum class IntArithmetics : BinaryOperator<Int>, IntBinaryOperator {
PLUS {
override fun apply(t: Int, u: Int): Int = t + u
},
TIMES {
override fun apply(t: Int, u: Int): Int = t * u
};
override fun applyAsInt(t: Int, u: Int) = apply(t, u)
}
fun main() {
val t = 2
val u = 3
println("PLUS($t, $u) = ${IntArithmetics.PLUS.apply(t, u)}");
println("TIMES($t, $u) = ${IntArithmetics.TIMES.apply(t, u)}");
}
Output:
PLUS(2, 3) = 5
TIMES(2, 3) = 6
Working with enum constants
An enum class has synthetic methods that can return a list of defined enum constants and retrieve an enum constant by enum name.
The signatures of these methods are as follows.
| Method | Description |
|---|---|
EnumClass.valueOf(value: String): EnumClass |
Returns the enum constant that matches the string passed as an argument. |
EnumClass.values(): Array<EnumClass> |
Creates and returns an array containing all constants of the enum. |
The example below retrieves a specific enum value and the list of enum class values.
fun main() {
println(Color.valueOf("RED").name)
println(Color.values().joinToString())
}
Output:
RED
RED, GREEN, BLUE
The valueOf() method throws IllegalArgumentException if there is no matching enum constant.
You can access enum class constants generically through the enumValues<T>() and enumValueOf<T>() functions.
enum class RGB { RED, GREEN, BLUE }
inline fun <reified T : Enum<T>> printAllValues() {
print(enumValues<T>().joinToString { it.name })
}
fun main() {
printAllValues<RGB>() // prints RED, GREEN, BLUE
}
Output:
RED, GREEN, BLUE
Every enum constant has properties that return its name (.name) and position (.ordinal) in the enum definition.
| Method | Description |
|---|---|
val name: String |
Returns the enum name. |
val ordinal: Int |
Returns the enum index. |
The example below retrieves the name and position.
fun main() {
println(Color.RED.name)
println(Color.RED.ordinal)
}
Output:
RED
0