Can abstract classes be in an allow only list in EK9?

← Sealed Types and Traits · Ref: Q300

No, abstract classes cannot appear in a trait's 'allow only' list. The list defines the exhaustive set of concrete runtime types that may implement the trait. Since abstract classes cannot be instantiated, listing them is meaningless.

ABSTRACT CLASSES ARE EXEMPT

Abstract classes can still implement sealed traits freely. They are exempt from the 'allow only' enforcement check because they cannot create runtime instances:

  AbstractHelper with trait of SealedTrait as abstract
    override doWork()
      content <- "Abstract"
      require content?

BUT NOT IN THE LIST

The 'allow only' list may contain only concrete classes, so naming an abstract one is rejected with E05250:

  defines module demo.sealed
    defines trait
      SealedTrait allow only AbstractBase, ConcreteA  //ERROR E05250
        doWork() as abstract
    defines class
      AbstractBase with trait of SealedTrait as abstract
        override doWork()
          content <- "Abstract"
          require content?
      ConcreteA with trait of SealedTrait
        override doWork()
          content <- "A"
          require content?

The corrected list names only the concrete class: 'SealedTrait allow only ConcreteA'.

TRANSITIVE CHECKING

Concrete subclasses of an abstract helper class that implements a sealed trait will be checked transitively. They must be in the 'allow only' list or get E05240.

See Q298 for 'allow only' basics. See Q299 for dispatcher exhaustiveness. See Q607 for why sealed classes must be open.

Example

defines module qa.sealedtraits.abstract.list

  defines trait

    Workable allow only ConcreteAlpha, ConcreteBeta
      doWork() as abstract

  defines class

    //AbstractHelper implements the sealed trait - allowed (abstract exempt)
    AbstractHelper with trait of Workable as abstract
      override doWork()
        content <- "Abstract"
        require content?

    //ConcreteAlpha is in the allow only list - allowed
    ConcreteAlpha with trait of Workable
      override doWork()
        content <- "Alpha"
        require content?

    //ConcreteBeta is in the allow only list - allowed
    ConcreteBeta is AbstractHelper
      override doWork()
        content <- "Beta"
        require content?

  defines function

    testAbstractExemption()
      alpha <- ConcreteAlpha()
      beta <- ConcreteBeta()
      require alpha?
      require beta?

Common mistakes

E05120 — Implementing an abstract method from a trait requires 'override'. Without it the compiler reports E05120 because the method signature is inherited. See ek9 -h E05120 for details.

Incorrect:

ConcreteAlpha with trait of Workable
      doWork()

Correct:

ConcreteAlpha with trait of Workable
      override doWork()

E05240 — A concrete class extending AbstractHelper inherits the sealed trait Workable, so sealing is checked transitively. UnlistedClass is not in the 'allow only' list, so the compiler reports E05240. See ek9 -h E05240 for details.

Incorrect:

ConcreteBeta is AbstractHelper
      override doWork()
        content <- "Beta"
        require content?

    UnlistedClass is AbstractHelper
      override doWork()
        content <- "Unlisted"
        require content?

Correct:

ConcreteBeta is AbstractHelper
      override doWork()
        content <- "Beta"
        require content?

E05240 — ConcreteAlpha is no longer in the 'allow only' list for the sealed trait Workable, yet it is still declared with 'with trait of Workable'. Only ConcreteBeta is permitted to implement it, so the unlisted concrete class triggers E05240. See ek9 -h E05240 for details.

Incorrect:

Workable allow only ConcreteBeta

Correct:

Workable allow only ConcreteAlpha, ConcreteBeta
Other ways to ask this
  • Why can't abstract classes be in allow only?
  • What happens if I put an abstract class in allow only?
  • Does allow only work with abstract classes?

Coming from another language?

Java: sealed interfaces allow abstract classes in permits clause (different design choice). Kotlin: sealed hierarchy allows abstract intermediaries. Rust: no sealed traits, enums are always concrete. EK9: 'allow only' list is strictly for concrete types, abstract classes can implement freely but cannot be listed.

Keywords: runtime, abstract, only, allow, sealed, exhaustive, trait, permit, concrete, exempt, instantiate, allow-only, closed, list, class