How do I call one constructor from another using this()?

← Constructor Delegation · Ref: Q580

Use this() as the first statement in a constructor to delegate to another constructor of the same class. This avoids duplicating initialization logic.

BASIC DELEGATION

Call this() with arguments matching another constructor:

  Account()
    -> name as String
    this(name, 0.0)  //delegates to two-arg constructor
  Account()
    -> name as String, balance as Float
    this.name: name
    this.balance: balance

MUST BE FIRST STATEMENT

this() must be the very first statement in the constructor body. No code can execute before delegation (E05050).

CHAINING MULTIPLE

Constructors can chain through multiple levels:

  Account() -> this("anonymous") -> this("anonymous", 0.0)

Each level delegates to a more specific constructor.

NO CIRCULAR DELEGATION

Constructor chains must terminate. A circular chain (A calls B calls A) is a compile error.

See Q581 for super() delegation. See Q582 for delegation order rules. See Q583 for this() vs super() restrictions. See Q94 for constructor basics. See Q605 for why 'this' is invalid in standalone functions.

Example

defines module qa.constructor.thisdelegation

  defines class

    Account
      holder <- String()
      balance <- 0.0
      accountType <- String()

      //One-arg delegates to two-arg
      Account()
        -> holder as String
        this(holder, 0.0)

      //Two-arg delegates to three-arg
      Account()
        ->
          holder as String
          balance as Float
        this(holder, balance, "standard")

      //Three-arg: does the actual initialization
      Account()
        ->
          holder as String
          balance as Float
          accountType as String
        this.holder: holder
        this.balance: balance
        this.accountType: accountType

      holder() as pure
        <- rtn as String: holder

      balance() as pure
        <- rtn as Float: balance

      accountType() as pure
        <- rtn as String: accountType

      default operator ?

  defines program

    ThisDelegationDemo()
      stdout <- Stdout()

      //Uses one-arg constructor (delegates through chain)
      acc1 <- Account("Alice")
      stdout.println(`${acc1.holder()}: ${acc1.balance()} (${acc1.accountType()})`)

      //Uses two-arg constructor
      acc2 <- Account("Bob", 100.0)
      stdout.println(`${acc2.holder()}: ${acc2.balance()} (${acc2.accountType()})`)

      //Uses three-arg constructor directly
      acc3 <- Account("Charlie", 500.0, "premium")
      stdout.println(`${acc3.holder()}: ${acc3.balance()} (${acc3.accountType()})`)

Common mistakes

E05050 — The this() delegation call must be the very first statement in the constructor body. No field assignments or other code can appear before it. See ek9 -h E05050 for details.

Incorrect:

Account()
        -> holder as String
        this.holder: holder
        this(holder, 0.0)

Correct:

Account()
        -> holder as String
        this(holder, 0.0)
Other ways to ask this
  • How does constructor chaining work in EK9?
  • How do I delegate between constructors with this()?
  • What is this() in a constructor?

Coming from another language?

Java: this() constructor chaining, must be first statement. Python: no this() equivalent. Kotlin: primary constructor + this() delegation. C#: this() chaining, must be first. EK9: this() delegation with first-statement rule, E05050 if not first.

Keywords: this, constant, super, first, statement, delegation, constructor, chain, E05050