Write a generic Pair class with two type parameters A and B that holds two values.

← Generics · Ref: Q1268

Generic classes with multiple type parameters use 'of type (A, B)' syntax. Key rules:

1. MUST have a default constructor: 'default Pair() as pure'
2. MUST have a parameterised constructor with both type params
3. Constructors MUST be PUBLIC — private/protected on generics triggers E06060
4. If any constructor is pure, ALL must be pure (E05190)
5. Use 'operator $' (not 'override operator $') since there is no parent $ to override
6. Use 'default operator ?' for auto-generated isSet semantics

SYNTAX

  Pair of type (A, B)
    first as A?
    second as B?
    default Pair() as pure
    Pair() as pure
      ->
        a as A
        b as B
      first :=? a
      second :=? b
    operator $ as pure
      <- rtn as String: ...
    default operator ?

See Q194 for single-parameter generics. See Q645 for why generic constructors must be public. See Q1243 for two-param Transformer example.

Example

defines module qa.genericsdeep.pairtwoparams

  defines class

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

      Pair() as pure
        first :=? A()
        second :=? B()

      Pair() as pure
        ->
          a as A
          b as B
        first :=? a
        second :=? b

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

      default operator ?

  defines program

    PairDemo()
      stdout <- Stdout()

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

      coordPair <- Pair(3.14, 2.72)
      stdout.println(`Coordinates: ${coordPair}`)

      if nameAge?
        stdout.println("Pair is set")

Common mistakes

E06060 — Generic type constructors must be public so the type can be instantiated with any valid type parameter. Private or protected constructors prevent proper instantiation. See ek9 -h E06060 for details.

Incorrect:

      private Pair() as pure

Correct:

      Pair() as pure

E07110 — A non-abstract constructor must provide a body; removing the no-arg constructor's body leaves it with no implementation while it is not declared abstract. See ek9 -h E07110 for details.

Incorrect:

      Pair() as pure

Correct:

      Pair() as pure
        first :=? A()
        second :=? B()

E05110 — Generic classes have no parent $ operator to override. Use 'operator $' without 'override'. See ek9 -h E05110 for details.

Incorrect:

      override operator $ as pure

Correct:

      operator $ as pure
Other ways to ask this
  • Define a generic Pair of type (A, B) with a constructor, operator ?, and operator $.
  • How do I create a generic class with two type parameters in EK9?
  • Show me a Pair class that holds first and second values of different types.
  • In Java I'd write Pair<A, B> — what is the EK9 equivalent?

Coming from another language?

Java: class Pair<A, B> { A first; B second; }. Kotlin: data class Pair<A, B>(val first: A, val second: B). Rust: struct Pair<A, B> { first: A, second: B }. Python: from typing import Generic, TypeVar. EK9: 'Pair of type (A, B)' with explicit constructors, 'default operator ?' and 'operator $'.

Keywords: generic, default operator, of type, B, A, two type parameters, pair, constructor