Enums Workbook

Ten short exercises on Kotlin enums — constants, exhaustive when, constructor properties, methods, per-constant overrides, the built-in members, and implementing interfaces.

Practice problems for Enums in Kotlin. Each takes a minute or two. A couple auto-check: implement the function and press Run — hidden tests go green when you’re right and red (with a hint) when you’re not, all on JetBrains’ Kotlin server. The rest are attempt-then-reveal: fill in the TODO, press Run to try it, then click Show answer to check yourself. Nothing here is a trick question, just direct practice of the syntax from the lesson.

the basics

1. A simple enum

Declare enum class Suit with HEARTS, DIAMONDS, CLUBS, SPADES.

Try it — edit, then press Run enum class Suit { HEARTS } // TODO: add DIAMONDS, CLUBS, SPADES fun main() { println(Suit.HEARTS) }
Show answer Hide answer
enum class Suit { HEARTS, DIAMONDS, CLUBS, SPADES }

2. Exhaustive when

Implement isRed so it returns true for HEARTS and DIAMONDS, using a when with no else.

Implement it, then press Run to check import org.junit.Test import org.junit.Assert class Test { @Test fun reds() { Assert.assertTrue("HEARTS is red", isRed(Suit.HEARTS)) Assert.assertTrue("DIAMONDS is red", isRed(Suit.DIAMONDS)) Assert.assertFalse("SPADES is not red", isRed(Suit.SPADES)) } } //sampleStart enum class Suit { HEARTS, DIAMONDS, CLUBS, SPADES } fun isRed(suit: Suit): Boolean = false // TODO: a when with no else — true for HEARTS and DIAMONDS //sampleEnd
Show answer Hide answer
fun isRed(suit: Suit) = when (suit) {
    Suit.HEARTS, Suit.DIAMONDS -> true
    Suit.CLUBS, Suit.SPADES -> false
}

data and behavior

3. Constructor properties

Declare enum class Planet(val gravity: Double) with EARTH(9.8) and MARS(3.7).

Try it — edit, then press Run enum class Planet(val gravity: Double) { EARTH(9.8) // TODO: add MARS(3.7) } fun main() { println(Planet.EARTH.gravity) }
Show answer Hide answer
enum class Planet(val gravity: Double) {
    EARTH(9.8),
    MARS(3.7)
}

4. A method on the enum

Add a weightOf(mass: Double) method to Planet returning mass * gravity.

Try it — edit, then press Run enum class Planet(val gravity: Double) { EARTH(9.8), MARS(3.7); // TODO: add weightOf(mass: Double) returning mass * gravity } fun main() { println(Planet.EARTH.gravity) }
Show answer Hide answer
enum class Planet(val gravity: Double) {
    EARTH(9.8),
    MARS(3.7);

    fun weightOf(mass: Double) = mass * gravity
}

Note the ; after the last constant when members follow.

5. Per-constant behavior

Declare enum class Op with ADD and MULTIPLY, each overriding an abstract apply(a: Int, b: Int): Int.

Try it — edit, then press Run enum class Op { ADD, MULTIPLY; // TODO: give each constant its own apply — add for ADD, multiply for MULTIPLY fun apply(a: Int, b: Int): Int = a + b } fun main() { println(Op.ADD.apply(2, 3)) println(Op.MULTIPLY.apply(2, 3)) }
Show answer Hide answer
enum class Op {
    ADD { override fun apply(a: Int, b: Int) = a + b },
    MULTIPLY { override fun apply(a: Int, b: Int) = a * b };

    abstract fun apply(a: Int, b: Int): Int
}

built-in members

6. Iterate the values

Given Suit, print every constant. Use the built-in that lists them.

Try it — edit, then press Run enum class Suit { HEARTS, DIAMONDS, CLUBS, SPADES } fun main() { // TODO: print every Suit constant using the built-in that lists them }
Show answer Hide answer
for (s in Suit.entries) println(s)

(Suit.values() also works; entries is the newer, preferred form.)

7. Parse from a name

Turn the string "CLUBS" into the Suit.CLUBS constant.

Try it — edit, then press Run enum class Suit { HEARTS, DIAMONDS, CLUBS, SPADES } fun main() { // TODO: turn "CLUBS" into the Suit.CLUBS constant val suit = Suit.HEARTS println(suit) }
Show answer Hide answer
Suit.valueOf("CLUBS")

8. Name and position

Given val s = Suit.SPADES, get its name as a string and its zero-based position.

Try it — edit, then press Run enum class Suit { HEARTS, DIAMONDS, CLUBS, SPADES } fun main() { val s = Suit.SPADES // TODO: print its name (a String) and its zero-based position println(s) }
Show answer Hide answer
s.name      // "SPADES"
s.ordinal   // 3

interfaces

9. An enum implementing an interface

Given interface Describable { fun describe(): String }, declare enum class Level : Describable with LOW and HIGH, each describing itself.

Try it — edit, then press Run interface Describable { fun describe(): String } // TODO: make Level implement Describable, with LOW and HIGH each describing itself enum class Level { LOW, HIGH } fun main() { println(Level.LOW) }
Show answer Hide answer
interface Describable { fun describe(): String }

enum class Level : Describable {
    LOW { override fun describe() = "low" },
    HIGH { override fun describe() = "high" }
}

10. A shared property

Declare enum class HttpStatus(val code: Int) with OK(200) and NOT_FOUND(404), and look up HttpStatus.OK.code.

Try it — edit, then press Run enum class HttpStatus(val code: Int) { OK(200) // TODO: add NOT_FOUND(404) } fun main() { // TODO: look up HttpStatus.OK.code and print it println(HttpStatus.OK) }
Show answer Hide answer
enum class HttpStatus(val code: Int) {
    OK(200),
    NOT_FOUND(404)
}

HttpStatus.OK.code   // 200

Going deeper: per-value behavior and the ordinal trap

12. Behavior per constant

Give each Op its own apply: ADD adds, MUL multiplies.

Implement it, then press Run to check import org.junit.Test import org.junit.Assert class Test { @Test fun ops() { Assert.assertEquals(5, Op.ADD.apply(2, 3)) Assert.assertEquals(6, Op.MUL.apply(2, 3)) } } //sampleStart enum class Op { ADD, MUL; // TODO: declare abstract fun apply(a: Int, b: Int): Int and override per constant fun apply(a: Int, b: Int): Int = 0 } //sampleEnd
Show answer Hide answer
enum class Op {
    ADD { override fun apply(a: Int, b: Int) = a + b },
    MUL { override fun apply(a: Int, b: Int) = a * b };
    abstract fun apply(a: Int, b: Int): Int
}

Each constant is effectively an anonymous subclass overriding the abstract member.

13. Don’t persist the ordinal

You store an enum constant in a database. Should you save its ordinal or an explicit code property, and why? Reveal to check.

Show answer Hide answer

Save an explicit property (Role(val code: String)). The ordinal is the constant’s position, and reordering the constants silently shifts every ordinal — corrupting any stored data that relied on it. The name is stable, and a dedicated code is stable and decoupled from declaration order.


Back to the lesson, Enums in Kotlin, or on to the next one: interfaces.

Comments