skip to content

How do secondary constructors behave when a class has no primary constructor, including delegation to a superclass?

level: seniorimportance: nice to knowfreq 30%

answer

  1. No primary => no this(...) requirement
  2. Secondary may call super(...) directly
  3. Class header: no () after base when no primary
  4. init blocks run for every secondary, before its body
  5. Header has this(...) XOR super(...), not both

basics

~10 s

Without a primary constructor, a secondary constructor can fully initialize the object itself and may call the base class with super(...). There is no this(...) requirement because there is no primary to delegate to.

solid answer

~40 s

When a class omits a primary constructor, each secondary constructor is responsible for base-class initialization and may call super(...) explicitly in its delegation header, or delegate to another secondary via this(...). The compiler does not require this(...) here because no primary exists. Even without a primary constructor, any class-level init blocks and property initializers still run as part of every secondary constructor — they execute before the secondary body for whichever constructor is invoked. If you write the class header without parentheses (no primary) and the superclass has constructors, each secondary must supply super(...) appropriately, possibly with different base arguments per secondary.

code

kotlin · 7 lines
kotlin
open class Base(val tag: String)

class Child : Base {              // no primary constructor
    constructor() : super("default")
    constructor(tag: String) : super(tag)
    init { println("runs for every secondary") }
}

go deeper

for a junior

Recognizes a class can lack a primary constructor and be built via secondary constructors.

for a middle

Writes correct super(...) delegation and knows init blocks still run per invocation.

for a senior

Explains the this()-vs-super() rules across primary/no-primary cases and the header-parenthesis nuance.

for a principal

Guides when no-primary multi-constructor classes are warranted (e.g., framework base classes) versus refactoring to a single primary path.

## No primary constructor You can declare a class with **no primary constructor** by simply not putting parentheses (and parameters) after the class name. Then construction happens entirely through **secondary constructors**. ```kotlin class Logger { // no primary constructor val name: String constructor(name: String) { this.name = name } } ``` ## super(...) in secondary constructors When there's no primary constructor and the **superclass has a constructor**, each secondary constructor must initialize the base class with `super(...)` (or delegate to a sibling secondary via `this(...)`): ```kotlin open class Base(val tag: String) class Child : Base { // no primary, no () after Base constructor() : super("default") constructor(tag: String) : super(tag) } ``` Note `Child : Base` has **no parentheses** after `Base` because there's no primary constructor to pass base args; each secondary supplies them via `super(...)`. Contrast with the primary-constructor form, where you pass base args in the header and the primary calls super: ```kotlin open class Base(val tag: String) class Child(tag: String) : Base(tag) // primary delegates to super in header ``` ## init blocks still run Even without a primary constructor, class-level **property initializers** and **`init` blocks** still execute — they run for **every** secondary constructor invocation, **before** that secondary's body. So shared initialization isn't lost. ```kotlin class C { init { println("shared init") } constructor(x: Int) { println("ctor x=$x") } constructor() { println("ctor noarg") } } // C(5): shared init -> ctor x=5 // C(): shared init -> ctor noarg ``` ## this(...) vs super(...) summary - **Primary exists** -> secondary must use `this(...)`; the primary calls `super`. - **No primary** -> secondary uses `super(...)` (or `this(...)` to a sibling secondary that eventually calls super). - A secondary's delegation header may contain **either** `this(...)` **or** `super(...)`, never both.

  • Do init blocks run if a class has no primary constructor?
    Yes. Property initializers and init blocks run for every secondary constructor invocation, before that constructor's body executes.
  • Can a secondary constructor's header contain both this(...) and super(...)?
    No. The header may delegate with either this(...) (to another constructor of the same class) or super(...) (to the base class), but not both.

saying these in an interview costs you the question

  • Saying init blocks don't run when there is no primary constructor
  • Putting parentheses after the base class in the header while also using super(...) in secondaries
  • Using both this(...) and super(...) in one secondary header
  • Believing a secondary must always use this(...) even when no primary exists

context