Can a derived class dispatcher target a private handler in the parent?
← Dispatcher Validation · Ref: Q613
No. A dispatcher cannot target a private method from a parent class. Private methods are not visible to child classes, so dispatch to them would fail. The compiler catches this with E05180.
PRIVATE METHODS ARE INVISIBLE
When a child class defines a dispatcher, the dispatch targets must be accessible. Private methods in the parent are not inherited by children and cannot be dispatched to.
CORRECT ACCESS LEVELS
Dispatcher handlers should be protected (visible to children) or public (visible to all). If the handler is in the same class as the dispatcher, private is fine because the dispatcher and handler are in the same scope.
SAME-CLASS DISPATCHERS
When both dispatcher entry and handlers are in the same class, private handlers are perfectly valid. The E05180 check only fires when the dispatcher in a child class tries to reach a private method in a parent.
WHAT TO DO
If a parent method needs to be a dispatch target from child classes, change it from private to protected. If the method must remain private, move the dispatcher into the parent class.
See Q60 for dispatcher fundamentals. See Q95 for field visibility. See Q573 for access modifier rules on overrides. See Q614 for dispatcher type hierarchy validation.
Example
defines module qa.dispatchervalidation.access defines class Message as abstract content() as pure abstract <- rtn as String? default operator ? TextMessage extends Message body <- "text" TextMessage() -> body as String this.body: body override content() as pure <- rtn as String: body default operator ? AlertMessage extends Message alert <- "alert" AlertMessage() -> alert as String this.alert: alert override content() as pure <- rtn as String: alert default operator ? //CORRECT: Dispatcher and all handlers in same class MessageProcessor process() as dispatcher -> msg as Message <- rtn as String: msg.content() process() -> msg as TextMessage <- rtn as String: "Text: " + msg.content() process() -> msg as AlertMessage <- rtn as String: "Alert: " + msg.content() defines function testSameClassDispatcher() processor <- MessageProcessor() textMsg <- TextMessage("hello") alertMsg <- AlertMessage("warning") require processor.process(textMsg) == "Text: hello" require processor.process(alertMsg) == "Alert: warning"
Common mistakes
E50060 — The dispatcher entry parameter is Message. Every handler parameter must be a subtype of Message. String is not in the Message hierarchy. See ek9 -h E50060 for details.
Incorrect:
process()
-> msg as String
Correct:
process()
-> msg as TextMessage
E05220 — All dispatcher handlers must return the same type as the entry method. The entry returns String, so a handler returning Integer is incompatible. See ek9 -h E05220 for details.
Incorrect:
process()
-> msg as AlertMessage
<- rtn as Integer: 42
Correct:
process()
-> msg as AlertMessage
<- rtn as String: "Alert: " + msg.content()
E07820 — Only one method with a given name can be marked 'as dispatcher'. The entry point process() is already marked as dispatcher. Marking a handler method as dispatcher too triggers E07820. See ek9 -h E07820 for details.
Incorrect:
process() as dispatcher -> msg as TextMessage <- rtn as String: "Text: " + msg.content()
Correct:
process()
-> msg as TextMessage
<- rtn as String: "Text: " + msg.content()
Other ways to ask this
- What is E05180 in EK9?
- Why can't a dispatcher call private methods from a parent?
- What access level do dispatcher handlers need?
Coming from another language?
Java: method overloading resolution doesn't access private methods from child. C++: virtual dispatch doesn't apply to private methods. Python: no private methods (name mangling is convention). Kotlin: private methods invisible to subclasses. EK9: E05180 prevents dispatcher from targeting private parent methods.
Keywords: child, access, parent, validate, private, dispatch, class, protected, dispatcher, handler, E05180, visible, ambiguity