Can a permitted subclass also be sealed in EK9?

← Sealed Types and Traits · Ref: Q303

Yes! A permitted subclass can itself be sealed, creating a chained hierarchy. Enforcement is transitive: all descendants must appear in every ancestor's allow only list.

CHAINED SEALING EXAMPLE

  Vehicle allow only Car, Truck, Sedan, Hatchback as open
  Car extends Vehicle allow only Sedan, Hatchback as open
  Sedan extends Car
  Hatchback extends Car
  Truck extends Vehicle

TRANSITIVE ENFORCEMENT

Sedan and Hatchback extend Car, but Car extends Vehicle. Because Vehicle is sealed, Sedan and Hatchback must also appear in Vehicle's allow only list. This is transitive: every sealed ancestor must explicitly permit the descendant.

ENFORCEMENT AT EACH LEVEL

- Vehicle permits: Car, Truck, Sedan, Hatchback
- Car permits: Sedan, Hatchback only
- Truck is not sealed (any class could extend it if it were 'as open')

This works with both classes and traits. Each sealed level provides its own exhaustive set.

See Q301 for sealed class basics, Q298 for sealed traits.

Example

defines module qa.sealedclasses.chained

  defines class

    Vehicle allow only Car, Truck, Sedan, Hatchback as open
      describe()
        <- rtn as String: "Vehicle"

    Car extends Vehicle allow only Sedan, Hatchback as open
      override describe()
        <- rtn as String: "Car"

    Sedan extends Car
      override describe()
        <- rtn as String: "Sedan"

    Hatchback extends Car
      override describe()
        <- rtn as String: "Hatchback"

    Truck extends Vehicle
      override describe()
        <- rtn as String: "Truck"

  defines function

    testChainedSealing()
      sedan <- Sedan()
      hatchback <- Hatchback()
      truck <- Truck()
      require sedan?
      require hatchback?
      require truck?

Common mistakes

E05270 — EK9 classes are closed by default. Without 'as open', no subclass can extend Vehicle. The compiler reports E05030 because the type is not open for extension. See ek9 -h E05030 for details.

Incorrect:

Vehicle allow only Car, Truck, Sedan, Hatchback

Correct:

Vehicle allow only Car, Truck, Sedan, Hatchback as open

E05240 — Sedan and Hatchback extend Car which extends Vehicle. Because Vehicle is sealed, all concrete descendants including Sedan and Hatchback must appear in Vehicle's 'allow only' list. Omitting them triggers E05240. See ek9 -h E05240 for details.

Incorrect:

Vehicle allow only Car, Truck as open

Correct:

Vehicle allow only Car, Truck, Sedan, Hatchback as open

E05120 — Overriding the describe() method inherited from Vehicle requires the 'override' keyword. Omitting it triggers E05120. See ek9 -h E05120 for details.

Incorrect:

Car extends Vehicle allow only Sedan, Hatchback as open
      describe()
        <- rtn as String: "Car"

Correct:

Car extends Vehicle allow only Sedan, Hatchback as open
      override describe()
        <- rtn as String: "Car"

E50010 — SUV is not in 'Vehicle allow only Car, Truck, Sedan, Hatchback'. A concrete class must be listed in every sealed ancestor's 'allow only' list. Adding SUV without updating Vehicle's list triggers E50010. See ek9 -h E50010 for details.

Incorrect:

SUV extends Vehicle
      override describe()
        <- rtn as String: "SUV"

Correct:

Vehicle allow only Car, Truck, Sedan, Hatchback as open
Other ways to ask this
  • How does chained sealing work in EK9?
  • Can I have nested allow only in EK9?
  • How do I create a multi-level sealed hierarchy?

Coming from another language?

Java: sealed class hierarchies with permits at each level (Java 17+). Kotlin: sealed classes in same file, nested sealed hierarchies supported. EK9: chained allow only provides the same hierarchical sealing.

Keywords: exhaustive, permit, extend, chained, class, closed, nested, only, level, allow, allow-only, sealed, hierarchy