Kotlin Tutoial

Basics

Control Flow

Array & String

Functions

Collections

OOPs Concept

Exception Handling

Null Safety

Regex & Ranges

Java Interoperability

Miscellaneous

Android

Enum classes in Kotlin

In Kotlin, enum classes are a powerful way to define a set of constants with associated values and behaviors. Unlike Java, Kotlin's enum classes allow you to define methods, properties, and even initialize individual instances with specific values.

In this tutorial, we'll delve deep into enum classes in Kotlin.

1. Basic Enum Definition:

Define a simple enum for representing directions:

enum class Direction {
    NORTH, EAST, SOUTH, WEST
}

You can use the enum values like:

val currentDirection = Direction.NORTH
println(currentDirection)  // Outputs: NORTH

2. Initializing Enum Values:

Enum constants can have properties initialized with constructor values:

enum class Color(val r: Int, val g: Int, val b: Int) {
    RED(255, 0, 0),
    GREEN(0, 255, 0),
    BLUE(0, 0, 255);

    fun rgb() = (r * 256 + g) * 256 + b
}

Accessing the property:

val blueColor = Color.BLUE
println(blueColor.rgb())  // Outputs: 255

3. Enum Iteration:

You can iterate over all enum constants using the values() function:

for (direction in Direction.values()) {
    println(direction)
}

4. Finding Enum by Name:

The valueOf() function allows you to retrieve an enum constant by its name:

val southDirection = Direction.valueOf("SOUTH")
println(southDirection)  // Outputs: SOUTH

If the name doesn't match any of the enum constants, IllegalArgumentException will be thrown.

5. Enum Properties:

Each enum constant has a couple of inherent properties:

  • name: The name of the enum constant.
  • ordinal: The ordinal number (0-based) representing the position of the enum constant.
println(Direction.NORTH.name)      // Outputs: NORTH
println(Direction.NORTH.ordinal)   // Outputs: 0

6. Implementing Interfaces:

Enums in Kotlin can implement interfaces:

interface Printable {
    fun printMessage(): String
}

enum class Status: Printable {
    LOADING {
        override fun printMessage() = "Loading data..."
    },
    SUCCESS {
        override fun printMessage() = "Data loaded successfully!"
    },
    ERROR {
        override fun printMessage() = "An error occurred!"
    }
}

println(Status.LOADING.printMessage())  // Outputs: Loading data...

7. Anonymous Classes:

Just like Java, Kotlin allows you to give enum constants their own anonymous class bodies:

enum class Planet(val mass: Double, val radius: Double) {
    EARTH(5.97e24, 6.371e6) {
        override fun surfaceGravity() = 9.81
    },
    MARS(6.39e23, 3.39e6) {
        override fun surfaceGravity() = 3.71
    };
    
    abstract fun surfaceGravity(): Double
}

Conclusion:

Enum classes in Kotlin are a versatile construct, elevating the concept of enumeration to support a variety of use-cases beyond merely defining constants. This feature allows for organized, type-safe definitions with associated behaviors and properties, making it an essential tool in the Kotlin developer's toolkit.

Kotlin enum class example

Description: An example of a simple Kotlin enum class representing days of the week.

Code:

enum class Day {
    MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
}

fun main() {
    val today = Day.MONDAY
    println("Today is $today")
}

How to define enum classes in Kotlin

Description: Defining an enum class involves using the enum class keyword followed by the enum constants.

Code:

enum class Color {
    RED, GREEN, BLUE
}

Kotlin enum class vs regular class

Description: Enum classes in Kotlin are a special type of class designed for representing a fixed set of constants. They are more concise than regular classes for scenarios where a fixed set of instances is needed.

Code:

// Enum class
enum class Direction {
    NORTH, SOUTH, EAST, WEST
}

// Regular class
class DirectionClass(val name: String) {
    companion object {
        val NORTH = DirectionClass("North")
        val SOUTH = DirectionClass("South")
        val EAST = DirectionClass("East")
        val WEST = DirectionClass("West")
    }
}

Enum class with properties in Kotlin

Description: Enum classes in Kotlin can have properties associated with each enum constant.

Code:

enum class Planet(val mass: Double, val radius: Double) {
    EARTH(5.97e24, 6371.0),
    MARS(6.39e23, 3389.5),
    VENUS(4.87e24, 6051.8)
}

fun main() {
    val earth = Planet.EARTH
    println("Earth mass: ${earth.mass}, radius: ${earth.radius}")
}

Kotlin enum class with functions

Description: Enum classes can have functions associated with them, providing behavior specific to each enum constant.

Code:

enum class Operation {
    ADD {
        override fun apply(x: Int, y: Int): Int = x + y
    },
    SUBTRACT {
        override fun apply(x: Int, y: Int): Int = x - y
    },
    MULTIPLY {
        override fun apply(x: Int, y: Int): Int = x * y
    };

    abstract fun apply(x: Int, y: Int): Int
}

fun main() {
    val result = Operation.ADD.apply(10, 5)
    println("Result: $result")
}

Ordinal and values in Kotlin enum class

Description: The ordinal property represents the position of an enum constant, and the values() function returns an array of all enum constants.

Code:

enum class Season {
    SPRING, SUMMER, AUTUMN, WINTER
}

fun main() {
    val summer = Season.SUMMER

    println("Ordinal of $summer is ${summer.ordinal}")
    println("All seasons: ${Season.values().joinToString()}")
}

Kotlin enum class with constructor

Description: Enum classes can have constructors to initialize properties when each enum constant is defined.

Code:

enum class Size(val width: Int, val height: Int) {
    SMALL(10, 20),
    MEDIUM(20, 40),
    LARGE(30, 60)
}

fun main() {
    val medium = Size.MEDIUM
    println("Medium size: ${medium.width} x ${medium.height}")
}

Named arguments for enum classes in Kotlin

Description: Enum constants can be instantiated with named arguments, providing a more readable way to initialize properties.

Code:

enum class Language(val displayName: String, val yearIntroduced: Int) {
    KOTLIN(displayName = "Kotlin", yearIntroduced = 2011),
    JAVA(displayName = "Java", yearIntroduced = 1995),
    SWIFT(displayName = "Swift", yearIntroduced = 2014)
}

fun main() {
    val kotlin = Language.KOTLIN
    println("Language: ${kotlin.displayName}, Introduced: ${kotlin.yearIntroduced}")
}

Iterating over enum values in Kotlin

Description: Iterating over enum constants using a loop to perform operations on each constant.

Code:

enum class Direction {
    NORTH, SOUTH, EAST, WEST
}

fun main() {
    for (direction in Direction.values()) {
        println("Direction: $direction")
    }
}

Companion object in Kotlin enum class

Description: The companion object can be used in an enum class to define functions or properties associated with the entire enum class.

Code:

enum class Coin {
    PENNY, NICKEL, DIME, QUARTER;

    companion object {
        fun printDetails() {
            println("Coins in circulation: ${values().joinToString()}")
        }
    }
}

fun main() {
    Coin.printDetails()
}

Sealed classes vs enum classes in Kotlin

Description: Sealed classes and enum classes are both used to represent restricted hierarchies, but enum classes have a finite set of instances, while sealed classes can have multiple instances.

Code:

// Enum class
enum class Color {
    RED, GREEN, BLUE
}

// Sealed class
sealed class Result
data class Success(val data: String) : Result()
data class Error(val message: String) : Result()

Using when expression with enum classes in Kotlin

Description: Using the when expression to perform different actions based on the enum constant.

Code:

enum class TrafficLight {
    RED, YELLOW, GREEN
}

fun main() {
    val light = TrafficLight.RED

    when (light) {
        TrafficLight.RED -> println("Stop")
        TrafficLight.YELLOW -> println("Slow down")
        TrafficLight.GREEN -> println("Go")
    }
}

Custom methods in Kotlin enum classes

Description: Adding custom methods to enum classes to provide additional behavior.

Code:

enum class Coin {
    PENNY, NICKEL, DIME, QUARTER;

    fun getFullName(): String {
        return when (this) {
            PENNY -> "One Cent"
            NICKEL -> "Five Cents"
            DIME -> "Ten Cents"
            QUARTER -> "Twenty-Five Cents"
        }
    }
}

fun main() {
    val dime = Coin.DIME
    println("Coin: ${dime.name}, Full Name: ${dime.getFullName()}")
}