Why does the compiler require two constructors for my generic class?

← Generics · Ref: Q1071

EK9 generic types require exactly two constructors: a default (no-arg) constructor and a parameterised constructor.

Why two constructors?
1. The DEFAULT constructor creates an unset instance (needed for type inference)
2. The PARAMETERISED constructor creates a set instance with values

BEFORE (E06040 error — only one constructor):

  defines class
    Pair of type (A, B)
      first as A: A()
      second as B: B()
      Pair()
        ->
          first as A
          second as B
        this.first :=: first
        this.second :=: second

AFTER (fixed — both constructors):

  defines class
    Pair of type (A, B)
      first as A: A()
      second as B: B()
      default Pair()
      Pair()
        ->
          first as A
          second as B
        this.first :=: first
        this.second :=: second
      default operator ?

The parameterised (inferred) constructor must be public (E06060 rejects a private or protected one). The default constructor may be declared 'default private Pair()', but then code outside the type cannot create an empty one such as 'Pair() of (String, Integer)' (E06180); keep it public when callers need that.

See Q194 for generic class basics. See Q196 for multi-parameter generics. See Q116 for default operator.

Example

defines module qa.generics.twoconstructors

  defines class

    Pair of type (A, B)
      first as A: A()
      second as B: B()

      //Constructor 1: default (used by compiler for type inference)
      default Pair()

      //Constructor 2: parameterised (public — used by code)
      Pair()
        ->
          first as A
          second as B
        this.first :=: first
        this.second :=: second

      override operator ? as pure
        <- rtn as Boolean: first? and second?

      operator $ as pure
        <- rtn as String: `(${$first}, ${$second})`

  defines program

    GenericConstructorDemo()
      stdout <- Stdout()

      pair <- Pair("Alice", 30)
      stdout.println(`Pair: ${pair}`)

Common mistakes

E06040 — Generic types require 2 constructors: a default (no-arg) and a parameterised one. Add 'default Pair()' (or 'default private Pair()' if outside code must not create an empty one) for the default constructor. See ek9 -h E06040 for details.

Incorrect:

    Pair of type (A, B)
      first as A: A()
      second as B: B()

      //Constructor 2: parameterised (public — used by code)

Correct:

    Pair of type (A, B)
      first as A: A()
      second as B: B()

      //Constructor 1: default (used by compiler for type inference)
      default Pair()

      //Constructor 2: parameterised (public — used by code)
Other ways to ask this
  • What is E06040 and how do I fix it?
  • My generic class gets 'requires 2 constructors' error
  • How do I define constructors for a generic type in EK9?

Coming from another language?

Java: generics have no constructor requirements. Rust: no constructors, uses associated functions. EK9: generic types MUST have exactly 2 constructors — default (public, or 'default private' to stop outside code creating an empty one) and parameterised.

Keywords: E06040, two, default, generic, private, constructor, type