How does allow only work with dispatchers in EK9?
← Sealed Types and Traits · Ref: Q299
When a dispatcher's parameter type is a sealed trait (one with 'allow only'), the compiler requires handlers for all permitted types. This provides exhaustive matching, similar to Java's sealed switch or Kotlin's sealed when.
EXHAUSTIVE DISPATCH
A dispatcher on a sealed trait must have a handler for every type in the 'allow only' list:
ShapeProcessor
process() as dispatcher
-> shape as Shape
process()
-> circle as Circle
process()
-> square as Square
process()
-> triangle as Triangle
COMPILE-TIME SAFETY
When you add a new type to the 'allow only' list, every dispatcher that operates on that trait will fail to compile until a handler is added. This guarantees all dispatch points are updated.
UNSEALED TRAITS
Dispatchers on unsealed traits (without 'allow only') do not require exhaustive handlers. The entry point acts as a catch-all fallback.
See Q298 for 'allow only' basics. See Q105 for dispatcher patterns. See Q618 for sealed exhaustive dispatch deep dive.
Example
#!ek9 defines module qa.sealedtraits.dispatchers defines trait Shape allow only Circle, Square, Triangle area() as abstract <- rtn as Float? defines class Circle with trait of Shape override area() <- rtn as Float: 3.14 Square with trait of Shape override area() <- rtn as Float: 1.0 Triangle with trait of Shape override area() <- rtn as Float: 0.5 ShapeProcessor process() as dispatcher -> shape as Shape content <- "Unknown shape" require content? process() -> circle as Circle content <- "Circle" require content? process() -> square as Square content <- "Square" require content? process() -> triangle as Triangle content <- "Triangle" require content? defines function testDispatchers() processor <- ShapeProcessor() require processor?
Common mistakes
E05120 — Implementing a trait's abstract method requires the 'override' keyword. Omitting it causes E05120 because the compiler sees an inherited method being redefined without acknowledgement. See ek9 -h E05120 for details.
Incorrect:
Circle with trait of Shape area() <- rtn as Float: 3.14
Correct:
Circle with trait of Shape override area() <- rtn as Float: 3.14
E50001 — Renaming the variable means later references to 'processor' become unresolved, triggering E50001. Variable names must be consistent. See ek9 -h E50001 for details.
Incorrect:
processorXYZ <- ShapeProcessor() require processor?
Correct:
processor <- ShapeProcessor() require processor?
E05240 — A class not in the 'allow only' list cannot implement the sealed trait. Hexagon is not listed in 'Shape allow only Circle, Square, Triangle' so it triggers E05240. See ek9 -h E05240 for details.
Incorrect:
Shape allow only Circle, Square
Correct:
Shape allow only Circle, Square, Triangle
Other ways to ask this
- Does EK9 check exhaustive dispatch on sealed traits?
- How do I get exhaustive matching in EK9?
- What is the EK9 equivalent of Java sealed switch?
Coming from another language?
Java: sealed interfaces + switch expressions with exhaustive pattern matching (Java 21+). Kotlin: sealed classes/interfaces + when expression with exhaustive checking. Rust: enum variants + match expression with exhaustive checking. Scala: sealed traits + match expression. EK9: dispatchers on sealed traits with compile-time exhaustiveness checking.
Keywords: allow, allow-only, closed, complete, dispatch, dispatcher, exhaustive, handler, match, migrate, missing, only, permit, sealed, switch