Must a class with 'allow only' be declared as open?
← Type Hierarchy Constraints · Ref: Q607
Yes. A class that uses 'allow only' to restrict its permitted subclasses MUST be declared 'as open'. If a class has 'allow only' but is not 'as open', the compiler raises E05270.
WHY OPEN IS REQUIRED
The 'allow only' clause specifies which subclasses may extend this class. But if the class is not 'as open', no class can extend it at all. Having 'allow only' on a closed class is contradictory: you're listing permitted subclasses for a class that permits no subclasses.
CORRECT PATTERN
Always combine 'allow only' with 'as open':
Shape allow only Circle, Square as open area() as abstract
This declares Shape as extensible but only by Circle and Square.
TRAITS ARE DIFFERENT
Traits are inherently open (they must be implementable). The E05270 check applies specifically to classes, which are closed by default in EK9.
ABSTRACT CLASSES
Abstract classes are implicitly open (they must be extensible to be useful). So 'abstract' classes with 'allow only' don't need an explicit 'as open' modifier.
See Q298 for allow only basics. See Q300 for abstract exemption in allow only lists. See Q301 for sealed class basics. See Q608 for sealed classes vs sealed traits. See Q101 for closed-by-default philosophy.
Example
defines module qa.typehierarchy.sealedopen defines class //CORRECT: 'allow only' combined with 'as open' Shape allow only Circle, Square as open name() <- rtn as String: "shape" Circle extends Shape override name() <- rtn as String: "circle" Square extends Shape override name() <- rtn as String: "square" defines class //CORRECT: abstract class with 'allow only' (abstract is implicitly open) Event allow only ClickEvent, KeyEvent as abstract eventType() as abstract <- rtn as String? default operator ? ClickEvent extends Event override eventType() <- rtn as String: "click" default operator ? KeyEvent extends Event override eventType() <- rtn as String: "key" default operator ? defines function testSealedOpenClasses() circle <- Circle() square <- Square() require circle.name() == "circle" require square.name() == "square" testSealedAbstractClasses() click <- ClickEvent() key <- KeyEvent() require click.eventType() == "click" require key.eventType() == "key"
Common mistakes
E05270 — A class with allow only must be declared as open. Without as open, the class is closed by default and no subclasses can extend it, making the allow only list contradictory. See ek9 -h E05270 for details.
Incorrect:
Shape allow only Circle, Square
Correct:
Shape allow only Circle, Square as open
E05120 — When overriding the name method from the sealed parent Shape, the override keyword is mandatory. Omitting it triggers shadowing detection. See ek9 -h E05120 for details.
Incorrect:
name()
Correct:
override name()
Other ways to ask this
- What is E05270 in EK9?
- Why does 'allow only' require 'as open'?
- What happens if a sealed class is not open?
Coming from another language?
Java: sealed classes are implicitly extensible by permitted types (no separate 'open' keyword needed). Kotlin: sealed classes are abstract by default. C#: no equivalent. Rust: no class sealing. EK9: sealed classes with 'allow only' must explicitly be 'as open' (E05270), because classes are closed by default.
Keywords: class, extend, circular, only, subclass, type, define, E05270, exhaustive, allow, sealed, open, closed, hierarchy