What are the access modifier rules for method overrides?
← Override Mechanics · Ref: Q573
Note: override applies to both methods and operators (e.g., override operator ? as pure, override operator $ as pure).
When overriding a method, the override must use EXACTLY the parent's access modifier. You can neither narrow it nor widen it. The compiler reports E05130 for any difference.
THE RULE
Public parent method requires a public override. Protected parent method requires a protected override. Private methods cannot be overridden (not visible to children).
THE ERROR: E05130
E05130 ('methods with same signature have different access modifiers') fires when an override's access modifier differs from the parent's in either direction - a public parent method made protected in the child, or a protected parent method made public.
WHY THIS RULE
One method, one contract: the override is the same method as the parent's, so it keeps the same visibility. Narrowing would break code that calls the parent method polymorphically; widening would quietly publish what the parent chose to keep inside the hierarchy.
DEFAULT ACCESS
In EK9, methods without an explicit modifier are public. Use 'private' or 'protected' to restrict access.
NO PRIVATE OVERRIDE
Private methods are not inherited and cannot be overridden. They are invisible to child classes, and writing 'override private' is E07010 (remove 'override' when using 'private').
See Q570 for override basics. See Q572 for false override claims. See Q95 for field visibility.
Example
defines module qa.override.accessmodifiers defines constant MIN_ENHANCED_LENGTH <- 2 defines class Service as open //Public method (default) process() as pure -> request as String <- rtn as String: "processed: " + request //Protected method protected validate() as pure -> input as String <- rtn as Boolean: length input > 0 default operator ? //Correct: public override of public method EnhancedService extends Service override process() as pure -> request as String <- rtn as String: "enhanced: " + request //Correct: keep it protected - an override uses exactly the parent's //access modifier; widening it to public is E05130 as well override protected validate() as pure -> input as String <- rtn as Boolean: length input > MIN_ENHANCED_LENGTH default operator ? defines program AccessModifierRulesDemo() stdout <- Stdout() svc <- EnhancedService() stdout.println(svc.process("hello"))
Common mistakes
E07010 — A private method cannot be an override: private methods are not inherited, so 'override' and 'private' together are rejected. Keep the parent's access modifier (public here). See ek9 -h E07010 for details.
Incorrect:
override private process() as pure
Correct:
override process() as pure
E07010 — 'override private' is rejected outright: a private method is never an override. The override of a protected parent method must itself be protected. See ek9 -h E07010 for details.
Incorrect:
override private validate() as pure
Correct:
override protected validate() as pure
Other ways to ask this
- What is E05130 method access modifiers differ?
- Can I change the visibility of an overridden method?
- Can I make an override more or less restrictive?
Coming from another language?
Java: an override may widen visibility (protected to public) but not reduce it. Kotlin and C#: similar, with C# requiring the same access for overrides. EK9: stricter than Java - the override's access modifier must match the parent's exactly (E05130 for narrowing or widening).
Keywords: restrictive, modifier, protected, override, public, virtual, access, inherit, visibility, private, abstract, function, open, E05130