What happens if a dispatcher handler's parameter type is outside the hierarchy?
← Dispatcher Validation · Ref: Q614
Every dispatcher handler's parameter type must be a subtype of the dispatcher entry's parameter type. If a handler specifies a type that is not in the hierarchy, the compiler raises E05210.
WHY TYPE HIERARCHY MATTERS
Dispatchers route calls based on runtime type. The entry method declares a base type (e.g., Animal). Each handler declares a specific subtype (e.g., Dog, Cat). At runtime, the dispatcher checks the actual type and routes to the matching handler. If a handler type is not in the hierarchy, it can never match.
EXAMPLE OF THE ERROR
If the dispatcher entry takes Animal and a handler takes Vehicle, no Animal can ever be a Vehicle. The handler is unreachable and indicates a design error.
CORRECT PATTERN
All handlers must use subtypes of the entry's parameter type:
handle() as dispatcher -> a as Animal <- rtn as String: "animal" handle() -> a as Dog //OK: Dog extends Animal <- rtn as String: "dog" handle() -> a as Cat //OK: Cat extends Animal <- rtn as String: "cat"
SEPARATE DISPATCHERS FOR SEPARATE HIERARCHIES
If you need to dispatch on multiple unrelated type hierarchies, create separate dispatchers. Each dispatcher handles one hierarchy.
See Q60 for dispatcher fundamentals. See Q615 for return type matching. See Q619 for two-parameter dispatchers.
Example
defines module qa.dispatchervalidation.hierarchy defines class Animal as abstract speak() as pure abstract <- rtn as String? default operator ? Dog extends Animal override speak() as pure <- rtn as String: "woof" default operator ? Cat extends Animal override speak() as pure <- rtn as String: "meow" default operator ? Bird extends Animal override speak() as pure <- rtn as String: "tweet" default operator ? //CORRECT: all handler types are in the Animal hierarchy AnimalHandler handle() as dispatcher -> animal as Animal <- rtn as String: "Animal: " + animal.speak() handle() -> animal as Dog <- rtn as String: "Dog says: " + animal.speak() handle() -> animal as Cat <- rtn as String: "Cat says: " + animal.speak() handle() -> animal as Bird <- rtn as String: "Bird says: " + animal.speak() defines function testHierarchyDispatch() handler <- AnimalHandler() dog <- Dog() cat <- Cat() bird <- Bird() require handler.handle(dog) == "Dog says: woof" require handler.handle(cat) == "Cat says: meow" require handler.handle(bird) == "Bird says: tweet"
Common mistakes
E05210 — The dispatcher entry takes Animal. A handler parameter type must be a subtype of Animal. String is an existing type that is completely unrelated, so the handler would never match at runtime. See ek9 -h E05210 for details.
Incorrect:
handle() -> animal as String <- rtn as String: "Dog says: " + animal
Correct:
handle() -> animal as Dog <- rtn as String: "Dog says: " + animal.speak()
E05220 — The dispatcher entry returns String. All handlers must return the same type. A handler returning Integer would create an inconsistent return type. See ek9 -h E05220 for details.
Incorrect:
handle() -> animal as Cat <- rtn as Integer: 0
Correct:
handle() -> animal as Cat <- rtn as String: "Cat says: " + animal.speak()
Other ways to ask this
- What is E05210 in EK9?
- Why must dispatcher handler types be in the same hierarchy?
- Can a dispatcher handle unrelated types?
Coming from another language?
Java: method overloading doesn't check hierarchy, resolved at compile time. Kotlin: no runtime dispatcher, uses when + is checks. Rust: match on enum variants (closed hierarchy). Go: type switch operates on interfaces. EK9: E05210 enforces that all dispatcher handler parameter types are within the dispatch hierarchy.
Keywords: E05210, dispatch, subtype, unrelated, extends, handler, ambiguity, hierarchy, dispatcher, validate, parameter, type