How do I restrict which classes can extend my class in EK9?
← Sealed Types and Traits · Ref: Q301
EK9 supports 'allow only' on both traits AND classes. A sealed class must be declared 'as open' (since EK9 classes are closed by default) and lists the permitted subclasses.
SEALED CLASS SYNTAX
Declare the permitted subclasses after 'allow only', then mark the class as open:
Shape allow only Circle, Square, Triangle as open area() <- rtn as Float: 0.0
KEY DIFFERENCE FROM TRAITS
Classes are closed by default, so 'as open' is required. Traits are always open, so they don't need it.
CHAINED SEALING
A permitted subclass can itself be sealed:
Vehicle allow only Car, Truck, Sedan, Hatchback as open Car extends Vehicle allow only Sedan, Hatchback as open
This is identical to Java 17's sealed classes with 'permits' and Kotlin's sealed classes.
See Q298 for sealed traits, Q299 for dispatchers with sealed types.
Example
defines module qa.sealedclasses.allowonly defines class Shape allow only Circle, Square, Triangle as open area() <- rtn as Float: 0.0 Circle extends Shape override area() <- rtn as Float: 3.14 Square extends Shape override area() <- rtn as Float: 1.0 Triangle extends Shape override area() <- rtn as Float: 0.5 defines function testSealedClass() circle <- Circle() square <- Square() triangle <- Triangle() require circle? require square? require triangle?
Common mistakes
E05270 — EK9 classes are closed by default, and a class with an 'allow only' list must be declared 'as open' or the list could never be used. Without 'as open' the compiler reports E05270 on the sealed class (and then each subclass is also rejected because the type is not open for extension). See ek9 -h E05270 for details.
Incorrect:
Shape allow only Circle, Square, Triangle
Correct:
Shape allow only Circle, Square, Triangle as open
E05120 — Overriding a parent class method requires the 'override' keyword. Omitting it triggers E05120 because the method is inherited from Shape. See ek9 -h E05120 for details.
Incorrect:
Circle extends Shape area() <- rtn as Float: 3.14
Correct:
Circle extends Shape override area() <- rtn as Float: 3.14
E05240 — Pentagon extends Shape but is not in Shape's 'allow only Circle, Square, Triangle' list. A subclass of a sealed class that is not listed is rejected with E05240. See ek9 -h E05240 for details.
Incorrect:
Triangle extends Shape override area() <- rtn as Float: 0.5 Pentagon extends Shape override area() <- rtn as Float: 1.72
Correct:
Triangle extends Shape override area() <- rtn as Float: 0.5
E05240 — Hexagon is declared as a subclass of Shape but the 'allow only Circle, Square, Triangle' list was not updated. Extending a sealed class with a class that is not in the list triggers E05240. See ek9 -h E05240 for details.
Incorrect:
Square extends Shape override area() <- rtn as Float: 1.0 Hexagon extends Shape override area() <- rtn as Float: 2.6
Correct:
Square extends Shape override area() <- rtn as Float: 1.0
Other ways to ask this
- What is allow only on classes in EK9?
- How do sealed classes work in EK9?
- Can I use allow only on a class instead of a trait?
Coming from another language?
Java: sealed classes with 'permits' clause (Java 17+). Kotlin: sealed classes restrict subclasses to same file. Rust: no sealed classes, but enum variants provide similar exhaustiveness. Swift: no direct equivalent. EK9: 'allow only' on classes provides explicit listing of permitted subclasses.
Keywords: class, restrict, extend, open, permit, migrate, subclass, exhaustive, sealed, allow-only, allow, only, closed