How do I extend or specialize a generic type in EK9?

← Generics · Ref: Q197

EK9 allows extending generic types that are marked 'as open'. You create concrete specializations by providing specific type arguments.

OPEN GENERIC TYPES

Mark a generic type as open to allow extension:

  BaseList of type T as open
    items as List of T?

SPECIALIZATION VIA EXTENSION

Create a concrete type by extending with specific types:

  NameList is BaseList of String

NameList is now a concrete class with String-typed items.

ADDING METHODS

Specializations can add new methods:

  NameList is BaseList of String
    findByPrefix()
      -> prefix as String
      <- rtn as String?

GENERIC FUNCTION INSTANTIATION

Generic functions use 'is' or 'extends' for instantiation:

  intCompare <- () is compareFunc of Integer as function

See Q194 for generic classes. See Q101 for closed by default. See Q102 for as open. See Q58 for generic functions.

Example

defines module qa.generics.extending

  defines function

    compareFunc() of type T as open
      ->
        item1 as T
        item2 as T
      <-
        rtn as Integer := item1 <=> item2

  defines class

    BaseList of type T as open
      items as List of T?

      BaseList()
        items :=? List() of T

      BaseList()
        -> item as T
        items: List() of T
        items += item

      addItem()
        -> item as T
        if not items?
          items: List() of T
        items += item

      count() as pure
        <- rtn as Integer: 0
        if items?
          rtn: length items

      default operator ?

    // Specialization: concrete type from generic
    NameList is BaseList of String

      default operator ?

  defines program

    ExtendingGenericsDemo()
      stdout <- Stdout()

      // === GENERIC FUNCTION INSTANTIATION ===

      intCompare <- () is compareFunc of Integer as function
      result <- intCompare(10, 20)
      stdout.println(`Compare 10 vs 20: ${result}`)

      strCompare <- () extends compareFunc of String as function
      strResult <- strCompare("apple", "banana")
      stdout.println(`Compare apple vs banana: ${strResult}`)

      // === SPECIALIZED CLASS ===

      names <- NameList()
      names.addItem("Alice")
      names.addItem("Bob")
      stdout.println(`Name count: ${names.count()}`)

Common mistakes

E50020 — Generic functions must be instantiated with 'as function', not 'as class'. Using the wrong construct type triggers E50020 — type not resolved. See ek9 -h E50020 for details.

Incorrect:

intCompare <- () is compareFunc of Integer as class

Correct:

intCompare <- () is compareFunc of Integer as function
Other ways to ask this
  • How do I create a concrete type from a generic in EK9?
  • Can I extend a parameterized type in EK9?
  • How does generic specialization work in EK9?

Coming from another language?

Java: class NameList extends ArrayList<String>. C++: template specialization or typedef. Rust: type alias or newtype pattern. Go: type NameList = List[string] (no true specialization). Kotlin: class NameList : ArrayList<String>(). EK9: 'NameList is BaseList of String' with optional additional methods.

Keywords: inherit, extend, parameterized, specialize, open, type-parameter, concrete, generic, parameterize, type