Why must a default constructor be private when a class has uninitialised fields?

← Constructor Delegation · Ref: Q886

When a class has properties that are not initialised at declaration and the developer provides explicit constructors to initialise them, the default no-argument constructor must be made private. Otherwise callers could bypass the developer constructors and create objects with uninitialised properties.

THE PROBLEM

Without `default private`, the no-arg constructor is public:

  Greeter()          // Creates Greeter with uninitialised 'name'
  Greeter("Steve")   // Creates Greeter with name = "Steve"

Both are callable — the first leaves 'name' uninitialised.

THE FIX

Option 1: Make default constructor private:

  default private Greeter()

Option 2: Initialise all fields at declaration:

  name <- ""   // Always initialised, no E07175

See Q580 for constructor delegation. See Q582 for constructor chaining. See Q584 for abstract constructor patterns.

Example

defines module qa.constructordelegation.defaultprivate

  defines class

    <?-
      Greeter with initialised name property.
      Because name is initialised at declaration, there is
      no E07175 — the default constructor is safe.
    -?>
    Greeter
      name <- ""

      Greeter()
        -> inName as String
        name: inName

      greet()
        <- rtn as String: `Hello ${name}`

      default operator ?

  defines program

    DefaultConstructorPrivateDemo()
      stdout <- Stdout()

      greeter <- Greeter("Steve")
      stdout.println(greeter.greet())

Common mistakes

E07175 — When a class has uninitialised properties and developer constructors but no private default constructor, callers can create objects with uninitialised fields. Either initialise all fields at declaration or add 'default private ClassName()'. See ek9 -h E07175 for details.

Incorrect:

name as String?

Correct:

name <- ""
Other ways to ask this
  • What triggers E07175 DEFAULT_CONSTRUCTOR_MUST_BE_PRIVATE?
  • Why does EK9 require private default constructors with uninitialised properties?
  • How do I prevent creation of objects with uninitialised fields?

Coming from another language?

Java: adding any constructor suppresses the default constructor. C#: same as Java. Python: __init__ replaces default. Rust: no default constructor unless Default trait implemented. EK9: default constructor always exists but must be made private when uninitialised fields present.

Keywords: property, safety, field, default, class, E07175, constructor, private, uninitialised, initialisation