Why must a dispatcher method have a body in EK9?
← Classes and OOP · Ref: Q771
A dispatcher method routes calls to type-specific private overloads at runtime. The base dispatcher method MUST have a body — it serves as the default fallback when no specific overload matches the argument type.
DISPATCHER PATTERN
1. Declare a public method 'as dispatcher' taking a base type
2. Provide a body — this is the default handler
3. Add private overloads for specific types
4. Runtime routes to the most specific match
THIS EXAMPLE
The TypeProcessor class has a dispatcher method handle() that takes Any. The body returns a default description. Private overloads handle Integer and String specifically. The runtime automatically routes to the correct overload.
WHY A BODY IS REQUIRED
Unlike abstract methods (which have no body), dispatchers need a default implementation for the fallback case — when the argument type doesn't match any specific overload. Without this, the dispatcher has no behaviour for unmatched types.
COMMON MISTAKE
Developers assume dispatcher works like abstract — defining just the signature. But abstract means 'subclass provides implementation', while dispatcher means 'I route to overloads and handle the default case myself'.
See Q47 for dispatcher pattern. See Q51 for overloading vs dispatch. See Q768 for abstract methods (the opposite rule).
Example
defines module qa.classesandoop.dispatcherbody defines class TypeProcessor handle() as dispatcher -> item as Any <- rtn as String: "unhandled type" private handle() -> item as Integer <- rtn as String: `integer ${item}` private handle() -> item as String <- rtn as String: `string ${item}` default operator ? Describer describe() as dispatcher -> target as Any <- rtn as String: "unknown" private describe() -> target as Integer <- rtn as String: `number ${target}` default operator ? defines program ShowDispatcher() stdout <- Stdout() processor <- TypeProcessor() items <- [1, "hello", 3.14] for item in items result <- processor.handle(item) stdout.println(result) describer <- Describer() entries <- [99, true] for entry in entries output <- describer.describe(entry) stdout.println(output)
Common mistakes
E07120 — Removing the initialisation from the return variable leaves the dispatcher with no body. Dispatcher methods must have a default implementation for the fallback case. Provide a body that handles unmatched types. See ek9 -h E07120 for details.
Incorrect:
handle() as dispatcher -> item as Any <- rtn as String?
Correct:
handle() as dispatcher -> item as Any <- rtn as String: "unhandled type"
E07120 — The dispatcher describe() has no body — the return variable is declared but not initialised. Dispatchers are not abstract; they need a working default implementation. See ek9 -h E07120 for details.
Incorrect:
describe() as dispatcher -> target as Any <- rtn as String?
Correct:
describe() as dispatcher -> target as Any <- rtn as String: "unknown"
Other ways to ask this
- What triggers E07120 dispatcher but no body provided?
- How do I write a dispatcher method in EK9?
- What is the dispatcher pattern in EK9?
Coming from another language?
Java: no built-in dispatch, manual instanceof chains or visitor pattern. Python: functools.singledispatch for function-level dispatch. Kotlin: no built-in multi-dispatch, use sealed class + when. Rust: no multi-dispatch, use enum + match. Go: no dispatch, use type switch. EK9: 'as dispatcher' keyword with automatic runtime type routing.
Keywords: runtime, method, default, routing, E07120, overload, dispatcher, type, body, dispatch