Why can't I mark a method 'protected' in a closed class?
← Classes and OOP · Ref: Q1317
The 'protected' access modifier only makes sense for inheritance: it grants access to subclasses while hiding the member from outside code. A class that is closed (the EK9 default) can never have subclasses, so 'protected' would be meaningless there. EK9 rejects it at compile time with E07260.
THE FIX
There are two correct paths depending on intent:
1. If you DO intend the class to be extended, mark the class 'as open'. Then 'protected' is valid because subclasses exist to use it. 2. If no inheritance is intended, use 'private' instead. A private method is fully encapsulated and needs no open class.
WHY EK9 IS STRICT
In Java you can write 'protected' in a final class and it silently behaves like package-private nonsense; the modifier is dead. EK9 eliminates that dead, misleading code: 'protected' must match a real inheritance relationship or it does not compile.
See Q102 for 'as open'. See Q101 for closed-by-default. See Q573 for override access modifier rules.
Example
defines module qa.oop.protected.open defines class //CORRECT: the class is 'as open', so 'protected' is meaningful - //subclasses can call validate() while outside code cannot. Account as open balance as Float: 0.0 Account() -> opening as Float this.balance: opening //Protected: visible to subclasses, hidden from the outside world. protected validate() as pure <- rtn as Boolean: balance >= 0.0 describe() <- rtn as String: `Account balance ${balance}` default operator ? //Subclass exercises the protected method - the reason 'protected' exists. SavingsAccount extends Account SavingsAccount() -> opening as Float super(opening) isHealthy() as pure <- rtn as Boolean: validate() default operator ? defines program ProtectedRequiresOpenDemo() stdout <- Stdout() savings <- SavingsAccount(100.0) stdout.println(savings.describe()) stdout.println(`Healthy: ${savings.isHealthy()}`)
Common mistakes
E07260 — 'protected' grants access to subclasses, but a closed class (the EK9 default) can never be extended, so the modifier is meaningless and triggers E07260. Either mark the class 'as open' so subclasses exist to use the protected method, or use 'private' if no inheritance is intended. See ek9 -h E07260 for details.
Incorrect:
Account protected validate() as pure <- rtn as Boolean: true
Correct:
Account as open balance as Float: 0.0
Other ways to ask this
- What triggers E07260 METHOD_MODIFIER_PROTECTED_IN_CLOSED_CLASS?
- Why does EK9 reject 'protected' on a method in a non-open class?
- When is the 'protected' access modifier valid on a class method?
Coming from another language?
Java: 'protected' compiles even on a 'final' class, where it can never be exercised by a subclass - the modifier is silently dead code. Kotlin: 'protected' is allowed on a final class with only a warning at most. C#: 'protected' on a sealed class is permitted but useless. EK9: compile-time error E07260 - 'protected' requires the class to be 'open' (or abstract, which is implicitly open), otherwise use 'private'.
Keywords: open, class, access, E07260, inheritance, method, subclass, modifier, protected, private, visibility, closed