Enum classes in Kotlin
This is a chapter from the book Kotlin Essentials. You can find it on LeanPub.
In this chapter, we're going to introduce the concept of enum classes. Let's start with an example. Suppose that you’re implementing a payment method that has to support three possible options: cash payment, card payment, and bank transfer. The most basic way to represent a fixed set of values in Kotlin is an enum class. Inside its body, we list all the values, divided by a comma. We name values using UPPER_SNAKE_CASE notation (e.g.,
BANK_TRANSFER). Enum class elements can be referenced by the enum name, followed by a dot, and then the value name (e.g.,
PaymentOption.CASH). All values are typed as the enum class type.
Each enum class has the following companion object functions:
values, which returns an array of all the values of this enum class;
valueOf, which parses a string into a value matching its name (this is case-sensitive) or throws an exception.
Instead of these methods, we can also use the top-level
As you can see, enum elements keep their values in order. This order is important. Each enum value has two properties:
name- the name of this value,
ordinal- the position of this value (starting from 0).
Each enum class is a subclass of the abstract class
Enum. This superclass guarantees the
ordinal properties. Enum classes have properties that implement
hashCode, but, unlike data classes, they also have
compareTo (their natural order is the order of the elements in the body).
Enum values can be used inside when-conditions. Moreover, there is no need to use the else-branch when all possible enum values are covered.
Enum classes are very convenient because they can be easily parsed or stringified. They are a popular way to represent a finite set of possible values.
Data in enum values
In Kotlin, each enum value can hold a state. It is possible to define a primary constructor for an enum class, and then each value needs to specify its data next to its name. It is a best practice that enum values should always be immutable, so their state should never change.
Enum classes with custom methods
Kotlin enums can have abstract methods whose implementations are item-specific. When we define them, the enum class itself needs to define an abstract method, and each item must override it:
This option is not popular as we generally prefer using functional primary constructor parameters1 or extension functions2.
Enum classes are a convenient way to represent a concrete set of possible values. Each value has the properties
ordinal (position). We can get an array of all values using the
values companion object function or the
enumValues top-level function. We can also parse an enum value from
String using the
valueOf companion object function or the
enumValueOf top-level function.
In the next chapter, we will talk about sealed classes, which are often treated as similar to enums but represent completely different and even more powerful abstractions. Sealed classes can form a closed hierarchy of classes, whereas enums represent only a set of constant values.
Functional variables are described in the book Functional Kotlin. An example of using an enum class with functional primary constructor parameters is presented in Effective Kotlin, Item 41: Use enum to represent a list of values.
Extension functions are described later in this book.