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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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