E07175: default constructor must be 'private' when uninitialised properties exist

Category: E07xxx Full resolution · Reported in phase: PRE_IR_CHECKS · Classification: DEFAULT_CONSTRUCTOR_MUST_BE_PRIVATE · All error codes

What went wrong

A class has uninitialised properties and developer-coded constructors, but the default (no-argument) constructor is still public. This allows callers to bypass the developer constructors and create objects with uninitialised properties.

Worked examples

Compilable examples demonstrating this error and the correct fix:

  • ek9 -q 886 (Why must a default constructor be private when a class ha...)

How to fix it

  1. Add 'default private ClassName()' to make the default constructor private
  2. Or initialise all properties at declaration (e.g., name <- "")
  3. The goal is to ensure every externally callable constructor initialises all properties

Common causes

  • Added a constructor for initialisation but forgot to restrict the default constructor
  • Assumed that adding a developer constructor would suppress the default one (it does not in EK9)

See also

  • E07170: no developer constructor at all with uninitialised properties
  • E07080: invalid default constructor with parameters

Examples

Every example is compiled by the EK9 compiler: the first fails exactly as captioned, the others fix it.

Fails with E07175: default constructor must be 'private' when uninitialised properties exist

#!ek9
defines module error.e07175.bad

  defines class

    //owner is unset until a constructor sets it, yet a public no-argument constructor is generated
    Account
      owner as String?

      Account()
        -> name as String
        this.owner: name

      describe() as pure
        <- rtn as String: `Owned by ${owner}`

      default operator ?

Fixed: Make the no-argument constructor private

#!ek9
defines module error.e07175.good

  defines class

    Account
      owner as String?

      //Only the class itself can make an Account with no owner
      default private Account()

      Account()
        -> name as String
        this.owner: name

      describe() as pure
        <- rtn as String: `Owned by ${owner}`

      default operator ?

Questions and answers

These Q&A entries show E07175 and its fix: