What is allow only on traits in EK9?

← Sealed Types and Traits · Ref: Q298

The 'allow only' clause on a trait creates a sealed trait, restricting which classes may implement it. Only the classes explicitly listed can use 'with trait of' to implement the trait.

SEALED TRAIT SYNTAX

Declare the permitted classes after 'allow only':

  Shape allow only Circle, Square, Triangle
    area() as abstract
      <- rtn as Float?

TRANSITIVE ENFORCEMENT

The restriction is checked transitively. If a class acquires the sealed trait through an intermediate trait or abstract class chain, it must still be in the 'allow only' list.

ABSTRACT EXEMPTION

Abstract classes are exempt from the check because they cannot be instantiated. The sealed set controls concrete runtime types only.

DYNAMIC CLASSES

Dynamic classes (anonymous classes created inline) are always rejected because their generated names cannot appear in an 'allow only' list.

See Q299 for how 'allow only' works with dispatchers. See Q300 for why abstract classes cannot be in the list. See Q607 for why sealed classes need 'as open'. See Q608 for sealed classes vs sealed traits. See Q609 for cross-module sealed enforcement.

Example

defines module qa.sealedtraits.allowonly

  defines trait

    Shape allow only Circle, Square, Triangle
      area() as abstract
        <- rtn as Float?

  defines class

    Circle with trait of Shape
      override area()
        <- rtn as Float: 3.14

    Square with trait of Shape
      override area()
        <- rtn as Float: 1.0

    Triangle with trait of Shape
      override area()
        <- rtn as Float: 0.5

  defines function

    testSealedTrait()
      circle <- Circle()
      square <- Square()
      triangle <- Triangle()
      require circle?
      require square?
      require triangle?

Common mistakes

E50001 — Renaming the variable means later references to 'circle' become unresolved, triggering E50001. Variable names must be consistent. See ek9 -h E50001 for details.

Incorrect:

circleXYZ <- Circle()

Correct:

circle <- Circle()

E05120 — When implementing a trait's abstract method, 'override' is required. Omitting it triggers E05120 because the method is inherited from the trait. See ek9 -h E05120 for details.

Incorrect:

Circle with trait of Shape
      area()
        <- rtn as Float: 3.14

Correct:

Circle with trait of Shape
      override area()
        <- rtn as Float: 3.14

E05240 — Only classes explicitly listed in the 'allow only' clause may implement the sealed trait. Adding Hexagon without listing it in 'Shape allow only Circle, Square, Triangle' triggers E02030. See ek9 -h E02030 for details.

Incorrect:

Shape allow only Circle, Square

Correct:

Shape allow only Circle, Square, Triangle
Other ways to ask this
  • How do I create a sealed trait in EK9?
  • How does EK9 restrict which classes can implement a trait?
  • What is the EK9 equivalent of Java sealed interfaces?

Coming from another language?

Java: sealed interfaces with 'permits' clause (Java 17+). Kotlin: sealed interfaces restrict implementations to same package/module. Rust: no sealed traits, but orphan rule prevents external trait implementations. Swift: no direct equivalent, uses access control. EK9: 'allow only' provides explicit listing of permitted concrete implementations.

Keywords: abstract, transitive, permit, class, anonymous, only, restrict, capture, migrate, closure, sealed, dynamic, allow-only, trait, exhaustive, allow, closed