Write a dispatcher with a fallback handler for unmatched types.

← Design Patterns and Idioms · Ref: Q1122

The base dispatcher method IS the fallback:

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

If no specific overload matches the runtime type, the base method runs. For sealed traits with exhaustive handlers, the fallback is never reached.

See Q1121 for sealed trait dispatch. See Q1123 for deep hierarchy.

Example

defines module qa.designpatterns.dispatcherfallback

  defines class

    Shape as open
      name()
        <- rtn as String: "Shape"

    Circle extends Shape
      override name()
        <- rtn as String: "Circle"

    Square extends Shape
      override name()
        <- rtn as String: "Square"

    //No specific handler for this type — falls through to base
    Hexagon extends Shape
      override name()
        <- rtn as String: "Hexagon"

    ShapeDescriber

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

      describe()
        -> shape as Circle
        <- rtn as String: "It is a Circle"

      describe()
        -> shape as Square
        <- rtn as String: "It is a Square"

  defines program

    DispatcherFallbackDemo()
      stdout <- Stdout()
      describer <- ShapeDescriber()

      //Matched handlers
      stdout.println(describer.describe(Circle()))
      stdout.println(describer.describe(Square()))

      //Fallback — no specific handler for Hexagon
      stdout.println(describer.describe(Hexagon()))

Common mistakes

E05030 — Types are closed by default. A class that other classes extend (Circle, Square and Hexagon extend Shape, which the dispatcher falls back to) must be declared 'as open', otherwise the compiler rejects the extension with E05030. See ek9 -h E05030 for details.

Incorrect:

Shape

Correct:

Shape as open
Other ways to ask this
  • I need a dispatcher that handles known types and has a default for everything else
  • In Java I'd use a default case in a switch. Write the EK9 dispatcher default handler
  • Given an open hierarchy, dispatch known types and fall back for unknown ones
  • Handle specific types with dedicated handlers and catch-all for the rest

Coming from another language?

Java: switch default case or else branch. Kotlin: sealed when + else. EK9: the dispatcher base method is the default — no separate 'default' keyword needed.

Keywords: dispatcher, fallback, catch-all, unmatched, default