skip to content

Enums Implementing Interfaces

An enum can implement interfaces, either once for the whole enum or per constant. It is how enums participate in the same abstractions as ordinary classes, which surprises people who think of them as plain constants.

part ofKotlinoverview, primer and where to startread it →
on this pageshow

questions

5

How does a Kotlin enum class implement an interface, and how can the implementation differ per enum constant?

level: juniorimportance: must knowfreq 55%

answer

  1. Colon in header lists interfaces
  2. Class-level override = shared; constant body = per-constant
  3. Constant body makes an anonymous subclass
  4. Semicolon separates constants from members
  5. Comma-separate multiple interfaces

basics

~10 s

Put the interface name after a colon in the enum header. You can implement the interface once for all constants, or let each constant override the method with its own version inside its body.

solid answer

~40 s

An enum class declares interfaces in its header just like a normal class: `enum class Op : Calc`. You then satisfy the interface either (1) once at the enum-class level, so every constant shares the same implementation, or (2) per constant, by giving each constant a body (`PLUS { override fun apply(...) = ... }`) that overrides the member. Constant bodies make each constant an anonymous subclass of the enum, so they can supply different behavior. You can mix both: provide a default at the class level and override only in some constants. The enum can implement multiple interfaces, separated by commas. Constants must come first, then a semicolon separates them from the rest of the body (functions, properties, class-level overrides).

code

kotlin · 12 lines
kotlin
interface Op { fun apply(a: Int, b: Int): Int }

enum class Arith : Op {
    PLUS  { override fun apply(a: Int, b: Int) = a + b },
    MINUS { override fun apply(a: Int, b: Int) = a - b };
}

fun main() {
    val r: Op = Arith.PLUS
    println(r.apply(7, 4)) // 11 (PLUS adds)
    println(Arith.MINUS.apply(7, 4)) // 3 (MINUS subtracts)
}

go deeper

for a junior

Knows the colon syntax and that an enum can implement an interface with a single shared override.

for a middle

Can choose between class-level and per-constant overrides and explains the semicolon rule.

for a senior

Explains each constant becomes an anonymous subclass and when to mix default + per-constant overrides.

for a principal

Frames enum+interface as a type-safe, exhaustive-when alternative to int-tag dispatch and weighs it against sealed types.

## What this is A Kotlin `enum class` is a special class with a fixed set of instances (the *constants*). Like any class it can implement one or more **interfaces** (a contract of methods/properties with no state of its own). You declare them in the header after a colon. ## Two ways to satisfy the interface ### 1. Class-level (shared) implementation The enum class provides one `override` and every constant inherits it. ```kotlin interface Named { val label: String; fun describe(): String } enum class Planet : Named { EARTH, MARS; override val label get() = name.lowercase() override fun describe() = "Planet $label" } ``` Here `EARTH.describe()` and `MARS.describe()` run the same code. ### 2. Per-constant implementation Each constant gets a **body** (`{ ... }`) and overrides the member itself. Internally each such constant becomes an **anonymous subclass** of the enum, so each can behave differently. ```kotlin interface Op { fun apply(a: Int, b: Int): Int } enum class Arith : Op { PLUS { override fun apply(a: Int, b: Int) = a + b }, TIMES { override fun apply(a: Int, b: Int) = a * b }; } ``` `Arith.PLUS.apply(2,3)` is 5, `Arith.TIMES.apply(2,3)` is 6. ## Syntax rules to remember - Constants are listed **first**. A **semicolon** (`;`) ends the constant list before any other members or class-level overrides. - A constant body is the block after the constant name; it may override `abstract` members of the enum or interface members. - An enum can implement **multiple** interfaces: `enum class X : A, B { ... }`. - You can mix styles: give a class-level default and override it only in selected constants. ## Why use it It couples a fixed set of named values with polymorphic behavior — a type-safe alternative to a `when` over an int constant. Each constant is still a singleton object, so identity (`===`) and `when` exhaustiveness still work.

  • Where must the semicolon go and why is it required here but optional in a simple enum?
    Right after the last constant, before any functions, properties, or overrides. It's required whenever the enum has body members beyond the constants; a constant-only enum can omit it.
  • Can different constants override the same interface method differently?
    Yes — that's the whole point of per-constant bodies; each constant is an anonymous subclass with its own override.

Each enum constant is a pre-built singleton; giving it a body is like handing that one singleton a custom job description that overrides the company default.

saying these in an interview costs you the question

  • Thinking an enum cannot implement interfaces at all
  • Forgetting the semicolon after the constant list
  • Believing all constants must share one implementation
  • Putting class-level functions before the constants
  • Confusing implementing an interface with extending a class (enums can't extend classes)

context

open as a page

Explain how abstract members and per-constant bodies interact when an enum implements an interface. What does the compiler generate, and how does dispatch work?

level: middleimportance: should knowfreq 35%

basics

~20 s

If the enum leaves an interface method abstract, every constant must give it a body. The compiler makes each such constant its own hidden subclass, so calling the method picks the right constant's version automatically.

open as a page

Show how a Kotlin enum can implement multiple interfaces while providing a class-level default that only some constants override. What are the constraints?

level: middleimportance: should knowfreq 40%

basics

~10 s

List the interfaces comma-separated after the colon. Implement one as a class-level default that all constants inherit, and override it only in the constants that need different behavior.

open as a page

When would you model behavior with an enum implementing an interface versus a sealed interface/class hierarchy? What trade-offs drive the choice?

level: seniorimportance: should knowfreq 30%

basics

~10 s

Use an enum-implementing-interface when you have a small fixed list of stateless named values that each carry behavior. Use a sealed hierarchy when variants need their own data fields or many instances.

open as a page

An enum implements an interface and you must dispatch/lookup constants by a runtime value while keeping the interface clean. How do you design this idiomatically in Kotlin?

level: seniorimportance: nice to knowfreq 18%

basics

~20 s

Keep the per-value behavior in each constant via the interface, and add a companion object with a lookup function (built from entries) to find the right constant from a runtime key. Callers use the interface, not the enum.

open as a page