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 class as open with the permitted subclasses:

  Shape as open allow only Circle, Square, Triangle
    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 as open allow only Car, Truck
  Car extends Vehicle as open allow only Sedan, Hatchback

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

E05030 — EK9 classes are closed by default. Without 'as open', no class can extend Shape. The compiler reports E05030 because the type is not open for extension. See ek9 -h E05030 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

E50010 — Pentagon is not in Shape's 'allow only' list. Attempting to extend a sealed class with an unlisted type is rejected by the compiler. See ek9 -h E50010 for details.

Incorrect:

Pentagon extends Shape

Correct:

Circle extends Shape

E50010 — Pentagon is not listed in 'Shape allow only Circle, Square, Triangle'. Extending a sealed class with a class not in the 'allow only' list triggers E50010 at PRE_IR_CHECKS. See ek9 -h E50010 for details.

Incorrect:

Pentagon extends Shape
      override area()
        <- rtn as Float: 1.72

Correct:

Shape allow only Circle, Square, Triangle as open
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: exhaustive, subclass, migrate, permit, open, extend, restrict, class, closed, only, allow, allow-only, sealed