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 no-arg constructor that gives each field an unset value: 'Pair() as pure' with 'first :=? A()' and 'second :=? B()'. A public 'default Pair() as pure' is rejected while 'first as A?' and 'second as B?' are uninitialised (E07175, plus E08060 for each field); 'default private Pair() as pure' is the alternative
2. MUST have a parameterised constructor with both type params
3. The parameterised constructor MUST be PUBLIC — a private one triggers E06060. A protected constructor is never allowed (E06060). Only the no-arg constructor may be private, either 'default private Pair() as pure' or a hand-written 'private Pair() as pure' with a body
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? 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: ... default operator ?
See Q194 for single-parameter generics. See Q1286 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 — A generic type's parameterised constructor must be public so the type can be instantiated (and inferred) with any valid type parameters; making it private triggers E06060, and a protected constructor is never allowed. Only the no-arg constructor may be private. See ek9 -h E06060 for details.
Incorrect:
private Pair() as pure -> a as A
Correct:
Pair() as pure -> a as A
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: A, B, of type, default operator, generic, constructor, pair, two type parameters