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 access modifier must be at least as permissive as the parent. You cannot make an override more restrictive. The compiler reports E05130 for violations.

THE RULE

Public parent method requires public override (same level). Protected parent method allows protected or public override (same or wider). Private methods cannot be overridden (not visible to children).

THE ERROR: E05130

E05130 fires when an override is more restrictive than the parent. For example, making a public parent method protected or private in the child.

WHY THIS RULE

Liskov Substitution Principle: if code calls parent.method(), it expects child.method() to be equally accessible. Reducing access would break polymorphic code.

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.

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: can widen protected to public
      //Or keep it protected (both are valid)
      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 — Making an override more restrictive than the parent is forbidden. The parent process() is public, so a private override would violate the Liskov Substitution Principle. See ek9 -h E07010 for details.

Incorrect:

override private process() as pure

Correct:

override process() as pure

E07010 — Narrowing a protected parent method to private in the child violates access modifier rules. The override must be at least as permissive as the parent. 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: same rule, cannot reduce visibility in override. Kotlin: same rule, override cannot be more restrictive. C#: same rule for virtual methods. EK9: E05130 enforces access modifier consistency in overrides.

Keywords: access, virtual, public, override, protected, modifier, restrictive, E05130, open, function, abstract, private, visibility, inherit