Write a dispatcher over a sealed Shape hierarchy with Circle, Square, and Triangle.

← Design Patterns and Idioms · Ref: Q1121

Define sealed trait, then dispatcher method with overloads:

  describe() as dispatcher
    -> shape as Shape
    <- rtn as String: "Unknown"
  describe()
    -> shape as Circle
    <- rtn as String: "Circle"

Mark the base method 'as dispatcher'. The compiler generates dispatch logic -- no instanceof, no casting.

See Q1122 for dispatcher with fallback. See Q1123 for deep hierarchy.

Example

defines module qa.designpatterns.dispatchersealed

  defines trait

    Shape allow only Circle, Square, Triangle
      name() as abstract
        <- rtn as String?

  defines class

    Circle with trait of Shape
      override name()
        <- rtn as String: "Circle"

    Square with trait of Shape
      override name()
        <- rtn as String: "Square"

    Triangle with trait of Shape
      override name()
        <- rtn as String: "Triangle"

    ShapeProcessor

      describe() as dispatcher
        -> shape as Shape
        <- rtn as String: "Unknown"

      describe()
        -> shape as Circle
        <- rtn as String: "Handled Circle"

      describe()
        -> shape as Square
        <- rtn as String: "Handled Square"

      describe()
        -> shape as Triangle
        <- rtn as String: "Handled Triangle"

  defines program

    DispatcherSealedDemo()
      stdout <- Stdout()
      processor <- ShapeProcessor()

      stdout.println(processor.describe(Circle()))
      stdout.println(processor.describe(Square()))
      stdout.println(processor.describe(Triangle()))

Common mistakes

E05240 — A sealed trait lists every type that may implement it. Triangle implements Shape but is missing from the 'allow only' list, so the compiler rejects it with E05240. Add the type to the list or do not implement the trait. See ek9 -h E05240 for details.

Incorrect:

Shape allow only Circle, Square

Correct:

Shape allow only Circle, Square, Triangle
Other ways to ask this
  • I need to handle different shape types without instanceof or casting
  • In Java I'd use instanceof checks or visitor pattern. Write the EK9 dispatcher
  • Given a sealed trait with three permitted types, dispatch on each type at runtime
  • Replace a chain of type checks with EK9's dispatcher mechanism

Coming from another language?

Java: instanceof + cast chain or visitor pattern. Kotlin: sealed class + when. Rust: enum + match. EK9: sealed trait + dispatcher — compiler generates dispatch, no casting.

Keywords: sealed, switch, trait, dispatcher, type, pattern matching