skip to content

Can a constant that has its own override body also pass constructor arguments? Show how per-constant bodies combine with a primary constructor and shared state.

level: middleimportance: should knowfreq 30%

answer

  1. NAME(args) { override ... } — args then body
  2. override body can read constructor vals
  3. abstract = must override, open = optional override
  4. mix shared concrete methods with per-constant ones
  5. companion object for factories/constants

basics

~10 s

Yes. Put the constructor arguments in parentheses after the constant name, then the override body in braces. Each constant can carry shared data and still have its own behavior.

solid answer

~30 s

An enum can declare a primary constructor; each constant passes its arguments in parentheses, and may *also* attach an anonymous body in braces for per-constant overrides. The order is `NAME(args) { override ... }`. The constructor-supplied properties are normal `val`s on the enum, accessible from inside each constant's overridden member via `this` or directly. This lets you combine **shared per-constant data** (a label, a symbol, a weight) with **per-constant behavior** (an overridden function). You can also call shared concrete helper methods declared in the enum body from within an override, mixing reuse and specialization.

code

kotlin · 12 lines
kotlin
enum class HttpStatus(val code: Int) {
    OK(200) { override fun isError() = false },
    NOT_FOUND(404) { override fun isError() = true },
    SERVER_ERROR(500) { override fun isError() = true };

    abstract fun isError(): Boolean
    fun describe() = "$code ${name} (error=${isError()})"
}

fun main() {
    println(HttpStatus.NOT_FOUND.describe()) // 404 NOT_FOUND (error=true)
}

go deeper

for a junior

Knows you can pass constructor args and add a body, in that order.

for a middle

Combines constructor data, shared concrete methods, and per-constant overrides; distinguishes abstract vs open.

for a senior

Designs a closed strategy family with shared helpers and selective open overrides, justifying the structure.

for a principal

Decides when configuration-plus-behavior belongs in the enum vs a separate sealed hierarchy or strategy registry.

## Combining data and behavior Enums support a **primary constructor** like any class. Each constant must invoke it with arguments. A constant can *additionally* carry a per-constant override body. The full form is: ```kotlin enum class Planet(val massKg: Double, val radiusM: Double) { EARTH(5.976e24, 6.378e6) { override fun displayName() = "Home" }, MARS(6.421e23, 3.397e6) { override fun displayName() = "The Red Planet" }; abstract fun displayName(): String // shared concrete behavior using constructor data fun surfaceGravity(): Double = G * massKg / (radiusM * radiusM) companion object { const val G = 6.67300e-11 } } ``` Key mechanics: - **Arguments first, body second**: `NAME(args) { ... }`. The parentheses feed the primary constructor; the braces are the anonymous subclass body. - The override body **can read** the constructor-backed `val`s (`massKg`, `radiusM`) because each synthetic subclass extends the enum, which holds those properties. - You can mix **abstract** members (each constant overrides) with **concrete** members like `surfaceGravity()` (shared by all). Constants may even override a concrete `open` member selectively. - A `companion object` can hold constants/factories (`const val G`, a `from(...)` lookup) without affecting per-constant behavior. ## Overriding `open` vs `abstract` - `abstract fun f()` — every constant **must** override. - `open fun f()` with a default body — constants override **only if** they want to differ; others inherit the default. ```kotlin enum class Signal { GREEN, // uses default RED { override fun isStop() = true }; open fun isStop() = false // default for the rest } ``` ## Why combine them This pattern centralizes a closed family: each constant = one strategy + its configuration data, all type-checked. No external map of enum -> behavior, no `when`. ## Gotchas - The terminating `;` is still required before the abstract/concrete members. - Overriding an `open` (not `abstract`) member is optional — easy to forget a constant and silently get the default.

  • If the enum member is `open` with a default instead of `abstract`, what changes?
    Constants override only when they need to differ; any constant without an override inherits the default body.
  • Can a constant's override call a shared concrete method declared in the enum?
    Yes — the synthetic subclass inherits all concrete members, so the override can call them or read constructor-backed properties.

saying these in an interview costs you the question

  • Putting the body before the constructor arguments
  • Believing data (constructor args) and behavior (override) are mutually exclusive
  • Forgetting that open members make override optional
  • Omitting the semicolon before the members
  • Thinking the override body cannot access constructor properties

context