skip to content

When a class has a primary constructor, what rule governs secondary constructors, and how does this(...) delegation work?

level: middleimportance: must knowfreq 55%

answer

  1. Primary present => secondary must use this(...)
  2. Direct or indirect delegation allowed
  3. Delegation goes after the colon in the header
  4. Primary always runs exactly once
  5. Chains: secondary -> secondary -> primary

basics

~10 s

If the class has a primary constructor, each secondary constructor must call it, directly or through another secondary constructor, using this(...). This guarantees the primary constructor always runs.

solid answer

~40 s

When a primary constructor is present, every secondary constructor must delegate to it either directly with this(args) in its delegation header, or indirectly by delegating to another secondary constructor that eventually reaches the primary. The delegation call appears after a colon in the constructor header, before the body. This is a compile-time requirement: omitting it is an error. The effect is that the primary constructor's initialization (and the property declarations and init blocks tied to it) always executes exactly once before the delegating secondary constructor's body. You can build delegation chains (secondary -> secondary -> primary). Each constructor in the chain may supply different argument values, including using default parameter values of the target.

code

kotlin · 7 lines
kotlin
class Rectangle(val width: Int, val height: Int) {
    constructor(side: Int) : this(side, side)   // -> primary
    constructor() : this(1)                      // -> secondary -> primary
}

val sq = Rectangle(5)   // 5x5
val unit = Rectangle()  // 1x1

go deeper

for a junior

Knows that this(...) calls the primary constructor and writes it after the colon.

for a middle

Explains the mandatory-delegation rule and builds direct and indirect delegation chains correctly.

for a senior

Explains why the rule exists (single canonical init path, properties initialized once) and how default/named args interact.

for a principal

Reasons about delegation in deep hierarchies and refactors toward a single primary path to keep initialization invariants enforceable.

## The delegation rule If a class declares a **primary constructor**, then **every secondary constructor must delegate to it** — either: 1. **Directly**, via `this(...)` in its header, or 2. **Indirectly**, by delegating to another secondary constructor that ultimately reaches the primary. This is enforced by the compiler. If you forget, you get a compile error. ## Syntax The delegation call goes **after a colon** in the constructor header: ```kotlin class Rectangle(val width: Int, val height: Int) { // direct delegation to primary constructor(side: Int) : this(side, side) // indirect delegation: -> the (side) constructor -> primary constructor() : this(1) } ``` - `constructor(side: Int) : this(side, side)` calls the **primary** constructor. - `constructor() : this(1)` calls the **other secondary** constructor, which then reaches the primary. ## Why the rule exists The primary constructor owns inline property declarations (`val width`, `val height`) and is logically the single canonical initialization path. Forcing delegation guarantees the primary constructor — and therefore those properties — is **always initialized exactly once**. ## Argument values can differ Each delegating constructor can pass any expression as arguments, including using **named arguments** and relying on the target's **default parameter values**: ```kotlin class Server(val host: String, val port: Int = 8080) { constructor(host: String) : this(host = host) // port uses default 8080 } ``` ## No primary constructor If there is **no** primary constructor, the delegation rule does not force `this(...)`; a secondary constructor may initialize directly. (It may instead delegate to a superclass with `super(...)`.) ## Common mistake You cannot put `super(...)` in a secondary constructor when a primary constructor exists and already handles the superclass — the secondary must route through `this(...)`, and the **primary** is the one that calls `super`.

  • Can a secondary constructor delegate to another secondary constructor?
    Yes. Indirect delegation is allowed as long as the chain eventually reaches the primary constructor (when one exists). Cyclic delegation is a compile error.
  • What happens if you omit this(...) on a secondary constructor of a class with a primary constructor?
    Compile error. With a primary constructor present, delegation is mandatory.

saying these in an interview costs you the question

  • Saying delegation is optional when a primary constructor exists
  • Putting the this(...) call inside the body instead of the header after the colon
  • Calling super(...) from a secondary constructor when a primary exists and routes super
  • Believing the primary constructor can be skipped via a secondary constructor

context