Can a generic class have multiple constructors in EK9, and do they all have to be public to avoid E06060?
← Generics · Ref: Q1287
Generic classes in EK9 can have as many constructors as they need — overloading, default, parameterised. The access rule is nuanced, not absolute: the PARAMETERISED (inferred) constructors must be public so the compiler can infer type arguments and instantiate from any context; the no-argument DEFAULT constructor may additionally be 'default private' as an escape hatch; and PROTECTED is never allowed on any generic constructor.
Error : E06060: 'Box' on line 15 position 22: a generic type does not support private or protected constructors
E06060 fires for a PROTECTED constructor (any), or for a PRIVATE PARAMETERISED constructor. It does NOT fire for a 'default private' no-arg constructor.
CORRECT: MULTIPLE PUBLIC CONSTRUCTORS
defines class
Box of type T item as T? label as String?
Box() as pure item :=? T() label :=? String()
Box() as pure -> initialItem as T item :=? initialItem label :=? String()
Box() as pure -> initialItem as T tag as String item :=? initialItem label :=? tag
Three constructors: no-argument, single-argument, two-argument. All public. All allowed. The no-arg constructor gives the conceptual field an unset 'T()' so it is present-but-unset, never null.
CORRECT: PRIVATE NO-ARG DEFAULT (the escape hatch)
defines class
Box of type T item as T?
default private Box() as pure // allowed: the no-arg default may be private
Box() as pure -> initialItem as T item :=? initialItem
When the field cannot be given an unset 'T()' (T may be abstract, may hold a function, or may have no public no-arg constructor), make the no-arg default private. External code then cannot create an empty Box; it must pass a value to the inferred constructor.
INCORRECT: PRIVATE OR PROTECTED PARAMETERISED CONSTRUCTOR
defines class
Box of type T item as T?
Box() as pure item :=? T()
private Box() as pure // E06060 — a parameterised constructor must be public -> initialItem as T item :=? initialItem
Type inference needs the parameterised constructor public, so making it private (or protected) is E06060.
HIDING VALIDATED CONSTRUCTION: A FACTORY FUNCTION
To route callers through validation, keep the public parameterised constructors and add a factory function in the same module:
defines function
createValidatedBox() as pure -> value as String <- rtn as Box of String? if value? rtn: Box(value)
Use 'default private' to forbid EMPTY construction; use a factory to control VALUED construction with validation, defaulting, or logging.
See Q1286 for the single-constructor form. See Q645 for the private no-arg escape hatch.
Example
defines module qa.genericsdeep.e06060multi defines class Box of type (T, U) first as T? second as U? Box() as pure first :=? T() second :=? U() Box() as pure -> firstValue as T secondValue as U first :=? firstValue second :=? secondValue getFirst() as pure <- rtn as T: first getSecond() as pure <- rtn as U: second override operator ? as pure <- rtn as Boolean: first? and second? operator $ as pure <- rtn as String: `(${first}, ${second})` defines program E06060MultiDemo() stdout <- Stdout() labelled <- Box(42, "answer") stdout.println($labelled) keyed <- Box("alpha", 3.14) stdout.println($keyed)
Common mistakes
E06060 — Generic types reject both 'private' and 'protected' constructor modifiers absolutely; a 'protected' constructor on a generic type fires E06060. See ek9 -h E06060 for details.
Incorrect:
protected Box() as pure first :=? T()
Correct:
Box() as pure first :=? T()
Other ways to ask this
- How do I write a generic class with more than one constructor in EK9?
- Does E06060 block protected constructors as well as private ones on generic types?
- Can I have an overloaded generic constructor where some are public and some are private?
- Why does my generic class with a default constructor and a parameterised constructor fail E06060?
Coming from another language?
C#/Java allow private constructors on generic types, commonly paired with static factory methods inside the same class for controlled construction. EK9 takes a different position: generic constructors are public by rule, and factory functions live alongside the generic in the same module. This keeps monomorphisation simple and the code-generation stage deterministic.
Keywords: multiple constructors, E06060, monomorphisation, generic type, constructor overloading, public constructor