skip to content

sealed class & sealed interface

sealed means the set of direct subtypes is known at compile time, subject to the module and package rules for where those subtypes may live. Interviewers compare it with an enum: sealed subtypes carry their own state, enum constants are fixed singletons.

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

questions

5

What is a sealed class (or sealed interface) in Kotlin, and what does the sealed modifier guarantee about its subtypes?

level: juniorimportance: must knowfreq 80%

answer

  1. Closed set of subtypes, known at compile time
  2. sealed class is implicitly abstract — instantiate subtypes
  3. Outside code cannot add new subtypes
  4. Subtypes can be data class / object / sealed
  5. Enables exhaustive when without else

basics

~20 s

A sealed class or interface is one where the compiler knows the complete, fixed list of all its direct subtypes. New subtypes can't be added from outside, so the set of possibilities is closed and known at compile time.

solid answer

~40 s

The sealed modifier marks a class or interface as a restricted hierarchy: the compiler knows every direct subtype at compile time, and no outside code can add more. A sealed class is also implicitly abstract, so you cannot instantiate it directly; you instantiate one of its subclasses. Subtypes must live in the same module and same package as the sealed declaration (the permitted-subtype rule). Sealed interfaces work the same way but, being interfaces, allow a type to implement several of them. The closed-set guarantee is what makes a when over the type exhaustive without an else branch. Typical subtypes are data classes, objects, or further sealed types. Compared to an enum, each subtype can hold its own distinct state and you can have multiple instances of a subtype.

code

kotlin · 8 lines
kotlin
sealed class PaymentMethod {
    data class Card(val last4: String) : PaymentMethod()
    data class Bank(val iban: String) : PaymentMethod()
    object Cash : PaymentMethod()
}

// PaymentMethod() // compile error: cannot create instance of sealed class
val pm: PaymentMethod = PaymentMethod.Cash

go deeper

for a junior

Can define a sealed class with a couple of subtypes and explain the closed-set idea in plain words.

for a middle

Knows it's implicitly abstract, distinguishes sealed class vs sealed interface, and connects the closed set to compiler exhaustiveness.

for a senior

Frames sealed as a restricted hierarchy used to model fixed alternatives and contrasts it precisely with open hierarchies and enums.

for a principal

Articulates the design intent — encoding invariants in the type system so illegal states are unrepresentable and changes are compiler-verified.

## What 'sealed' means The `sealed` keyword is a class/interface modifier that creates a **closed (restricted) type hierarchy**. 'Closed' means the compiler can see the *complete* set of direct subtypes at compile time, and nothing outside the declaration's allowed location can introduce new ones. ```kotlin sealed interface Shape data class Circle(val radius: Double) : Shape data class Rectangle(val width: Double, val height: Double) : Shape object Unknown : Shape ``` Here `Shape` has exactly three direct subtypes. No other file or library can add a fourth implementer. ## Key properties - **Implicitly abstract (for sealed *class*):** A `sealed class` cannot be instantiated directly — `Shape()` would not compile if `Shape` were a class. You create instances of its subtypes instead. Its constructors are effectively `protected` by default. - **A sealed *interface* is just an interface** with a closed implementer set. Because interfaces support multiple inheritance, one type can implement several sealed interfaces. - **Compile-time-known subtype set:** Because the set is fixed, the compiler can reason about completeness — this is what enables an exhaustive `when` without an `else`. - **Subtypes are normal types:** They can be `data class`, `object`, regular `class`, or even another `sealed` type, and each can carry its own state and behavior. ## Why use it Sealed types model 'one of a fixed set of things' — a value is *exactly one* of the known subtypes. This gives you type-safe alternatives that the compiler can check, unlike an open class hierarchy where any subtype could appear. ## Sealed vs open A plain `open class` or ordinary `interface` is **open**: any number of unknown subtypes can exist anywhere. `sealed` deliberately removes that openness to gain compile-time knowledge of the whole hierarchy.

  • Can you instantiate a sealed class directly?
    No. A sealed class is implicitly abstract; you instantiate one of its subtypes. A sealed interface also can't be instantiated since interfaces never can.
  • Does a sealed type prevent subclassing entirely?
    No — it restricts *who* can subclass and *where*. Subtypes are still allowed, but only within the same module and package as the sealed declaration.

Like a multiple-choice question with a fixed list of answers — the answer must be one of the printed options, and nobody can scribble in a new one.

saying these in an interview costs you the question

  • Saying a sealed class has no subtypes / can't be extended at all
  • Claiming you can instantiate a sealed class directly with its constructor
  • Thinking sealed means the same as final
  • Confusing sealed with enum (only one value per case)

context

open as a page

Where are subtypes of a sealed class or interface allowed to be declared? Explain the same-module / same-package permitted-subtype rule.

level: middleimportance: must knowfreq 65%

basics

~20 s

Direct subtypes must be in the same module as the sealed declaration, and in the same package. You can nest them inside the sealed type or put them in separate top-level files, as long as they stay in that module and package.

open as a page

When would you choose a sealed interface over a sealed class, and what capabilities differ between them?

level: middleimportance: should knowfreq 55%

basics

~20 s

Use a sealed interface when a type may need to belong to several closed hierarchies at once, since a class can implement many interfaces but extend only one class. Use a sealed class when you want shared state (stored properties) or a single constructor in the parent.

open as a page

How are sealed classes compiled on the JVM, and what are the rules around their constructors and instantiation?

level: seniorimportance: should knowfreq 35%

basics

~20 s

A sealed class compiles to an abstract class whose constructors are not accessible from outside, so it can't be subclassed or instantiated externally. Reflection can list its subclasses via sealedSubclasses, and the compiler tracks the permitted set.

open as a page

What are the consequences of adding a new subtype to a public sealed type, and how do sealed types interact with generic type parameters and variance?

level: principalimportance: nice to knowfreq 20%

basics

~20 s

Adding a subtype to a public sealed type is a breaking change for code that handles every case, because that code now misses one. Sealed types can be generic, and you can make the type parameter covariant with out to allow flexible subtyping.

open as a page