Bird
Raised Fist0
Kotlinprogramming~15 mins

Secondary constructors in Kotlin - Deep Dive

Choose your learning style10 modes available
Overview - Secondary constructors
What is it?
Secondary constructors in Kotlin are extra ways to create objects of a class besides the main constructor. They allow you to provide different sets of parameters to build an object. Each secondary constructor must either call the main constructor or another secondary constructor. This helps when you want flexible ways to create instances with different initial data.
Why it matters
Without secondary constructors, you would need to write many overloaded main constructors or use complex default parameters, making code harder to read and maintain. Secondary constructors let you offer clear, alternative ways to create objects depending on what information you have. This flexibility improves code clarity and usability in real projects.
Where it fits
Before learning secondary constructors, you should understand classes and primary constructors in Kotlin. After mastering secondary constructors, you can explore factory methods and data classes for more advanced object creation patterns.
Mental Model
Core Idea
Secondary constructors are alternative entry doors to create an object, each with its own set of keys (parameters), but all must lead through the main door (primary constructor).
Think of it like...
Imagine a house with one main front door and several side doors. Each door lets guests enter differently, but all paths lead inside the same house. Secondary constructors are like those side doors offering different ways to enter.
┌─────────────────────────────┐
│          Class Object        │
│                             │
│  ┌───────────────┐          │
│  │ Primary       │          │
│  │ Constructor   │◄─────────┤
│  └───────────────┘          │
│       ▲      ▲              │
│       │      │              │
│  ┌────┘      └─────┐        │
│  │ Secondary       │        │
│  │ Constructor 1   │        │
│  └─────────────────┘        │
│                             │
│  ┌─────────────────┐        │
│  │ Secondary       │        │
│  │ Constructor 2   │        │
│  └─────────────────┘        │
└─────────────────────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding primary constructors
🤔
Concept: Learn what a primary constructor is and how it initializes an object.
In Kotlin, a class can have one primary constructor defined in the class header. It sets up the initial state of the object. For example: class Person(val name: String, val age: Int) Here, 'name' and 'age' are parameters to create a Person object.
Result
You can create a Person like this: Person("Alice", 30). The primary constructor sets the name and age.
Understanding the primary constructor is essential because secondary constructors must connect to it, ensuring all objects are initialized consistently.
2
FoundationBasic syntax of secondary constructors
🤔
Concept: Introduce how to write a secondary constructor inside a class.
A secondary constructor is declared inside the class body using the 'constructor' keyword. It can have its own parameters and must call the primary constructor or another secondary constructor. Example: class Person(val name: String) { constructor(name: String, age: Int) : this(name) { // additional initialization } }
Result
You can create a Person with just a name or with a name and age using different constructors.
Knowing the syntax lets you provide multiple ways to create objects, improving flexibility.
3
IntermediateCalling primary constructor from secondary
🤔Before reading on: do you think a secondary constructor can create an object without calling the primary constructor? Commit to your answer.
Concept: Secondary constructors must delegate to the primary constructor to ensure consistent initialization.
Every secondary constructor must call the primary constructor directly or indirectly using 'this()'. This guarantees the primary constructor runs first. Example: class Person(val name: String) { constructor(name: String, age: Int) : this(name) { println("Age is $age") } }
Result
Creating Person("Bob", 25) calls the primary constructor with 'Bob' and then runs the secondary constructor code printing 'Age is 25'.
This rule prevents objects from being created without essential initialization, avoiding bugs.
4
IntermediateUsing secondary constructors for default values
🤔Before reading on: do you think secondary constructors are the only way to provide default values for parameters? Commit to your answer.
Concept: Secondary constructors can offer alternative ways to create objects with default or extra parameters.
Instead of default parameters, you can write a secondary constructor to provide default values. Example: class Person(val name: String, val age: Int) { constructor(name: String) : this(name, 0) // default age 0 } Person("Eve") creates a Person with age 0.
Result
You get flexible object creation with or without specifying age.
Secondary constructors provide a clear alternative to default parameters, useful in some design scenarios.
5
IntermediateMultiple secondary constructors chaining
🤔Before reading on: can secondary constructors call each other in a chain? Commit to your answer.
Concept: Secondary constructors can call other secondary constructors, forming a chain that ends at the primary constructor.
You can chain secondary constructors to reuse initialization logic. Example: class Person(val name: String, val age: Int) { constructor(name: String) : this(name, 0) constructor() : this("Unknown") } Here, the no-argument constructor calls the one-argument constructor, which calls the primary constructor.
Result
Person() creates a Person with name 'Unknown' and age 0 by chaining constructors.
Chaining reduces code duplication and centralizes initialization.
6
AdvancedSecondary constructors vs factory methods
🤔Before reading on: do you think factory methods and secondary constructors serve the same purpose? Commit to your answer.
Concept: Compare secondary constructors with factory methods as alternative object creation techniques.
Factory methods are functions that create objects, often with custom logic. Secondary constructors are part of the class and provide alternative constructors. Example factory method: class Person(val name: String) { companion object { fun fromAge(age: Int) = Person("Age $age") } } Person.fromAge(25) creates a Person differently than secondary constructors.
Result
Factory methods offer more flexibility, like returning subclasses or caching, beyond what secondary constructors can do.
Knowing the difference helps choose the right pattern for object creation complexity.
7
ExpertHow secondary constructors affect bytecode and performance
🤔Before reading on: do you think secondary constructors add runtime overhead compared to primary constructors? Commit to your answer.
Concept: Understand how Kotlin compiles secondary constructors to JVM bytecode and their impact on performance.
Kotlin compiles secondary constructors into additional constructor methods in bytecode. Each secondary constructor calls the primary constructor, so there is a small overhead of extra method calls. However, this overhead is minimal and usually optimized by the JVM. Using many secondary constructors can increase class size and complexity. Example bytecode shows multiple methods corresponding to constructors.
Result
Secondary constructors add slight overhead but improve code clarity; JVM optimizations minimize performance impact.
Understanding compilation helps balance design clarity with performance in large projects.
Under the Hood
When Kotlin compiles a class with secondary constructors, it generates multiple constructor methods in the JVM bytecode. Each secondary constructor method calls the primary constructor method using 'this()' delegation. This ensures the primary constructor's initialization code runs first. The JVM then executes the secondary constructor's additional code. This chaining guarantees consistent object setup regardless of which constructor is used.
Why designed this way?
Kotlin was designed to have a single primary constructor to centralize initialization logic, reducing errors and duplication. Secondary constructors provide flexibility for alternative initialization without breaking this centralization. This design balances simplicity and flexibility, avoiding the complexity of multiple primary constructors like in some other languages.
┌───────────────────────────────┐
│        Kotlin Class            │
│                               │
│  ┌───────────────┐            │
│  │ Primary       │            │
│  │ Constructor   │            │
│  └───────────────┘            │
│          ▲                    │
│          │ this() call         │
│  ┌───────┴────────┐           │
│  │ Secondary      │           │
│  │ Constructor 1  │           │
│  └────────────────┘           │
│          ▲                    │
│          │ this() call         │
│  ┌───────┴────────┐           │
│  │ Secondary      │           │
│  │ Constructor 2  │           │
│  └────────────────┘           │
└───────────────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Can a secondary constructor create an object without calling the primary constructor? Commit to yes or no.
Common Belief:Secondary constructors can create objects independently without calling the primary constructor.
Tap to reveal reality
Reality:Every secondary constructor must call the primary constructor or another secondary constructor, ensuring consistent initialization.
Why it matters:If this were false, objects could be created without essential setup, leading to bugs and inconsistent state.
Quick: Are secondary constructors the only way to provide default parameter values? Commit to yes or no.
Common Belief:Secondary constructors are the only way to give default values to constructor parameters.
Tap to reveal reality
Reality:Kotlin supports default parameter values directly in the primary constructor, often making secondary constructors unnecessary for defaults.
Why it matters:Misunderstanding this can lead to overly complex code when simpler default parameters would suffice.
Quick: Do secondary constructors and factory methods serve the exact same purpose? Commit to yes or no.
Common Belief:Secondary constructors and factory methods are interchangeable ways to create objects.
Tap to reveal reality
Reality:Factory methods are more flexible, can return subclasses or cached instances, while secondary constructors are limited to object initialization within the class.
Why it matters:Confusing these can limit design choices and lead to less maintainable code.
Quick: Does adding many secondary constructors significantly slow down your program? Commit to yes or no.
Common Belief:Using many secondary constructors causes noticeable runtime performance issues.
Tap to reveal reality
Reality:The JVM optimizes constructor calls, so the overhead is minimal and usually not a performance concern.
Why it matters:Worrying unnecessarily about performance can prevent writing clear, flexible code.
Expert Zone
1
Secondary constructors can only delegate to the primary constructor or another secondary constructor, never to super constructors directly, which affects inheritance design.
2
Using secondary constructors with default parameters can lead to ambiguous calls, so careful parameter design is needed to avoid compiler errors.
3
In data classes, secondary constructors are less common because primary constructors with default parameters usually suffice, but they can still be used for complex initialization.
When NOT to use
Avoid secondary constructors when default parameter values or factory methods can achieve the same goal more clearly. For complex object creation logic, prefer factory methods or builder patterns. Also, in data classes, rely on primary constructors with defaults instead of secondary constructors.
Production Patterns
In real-world Kotlin projects, secondary constructors are often used to provide legacy compatibility or alternative initialization paths. They are common in frameworks that require multiple ways to instantiate objects, such as Android development where XML inflation and code-based creation coexist.
Connections
Factory methods
Alternative object creation pattern
Understanding secondary constructors clarifies when to use factory methods, which offer more flexibility like returning subclasses or cached instances.
Constructor overloading in Java
Similar concept in another language
Knowing Kotlin's secondary constructors helps Java developers transition smoothly, as both provide multiple ways to create objects but Kotlin enforces delegation to a primary constructor.
User interface design
Designing multiple entry points
Just like secondary constructors offer multiple ways to create an object, UI design often provides multiple ways for users to achieve the same goal, emphasizing flexibility and user choice.
Common Pitfalls
#1Forgetting to call the primary constructor from a secondary constructor.
Wrong approach:class Person { constructor(name: String) { // missing call to primary constructor } }
Correct approach:class Person(val name: String) { constructor(name: String) : this(name) { // correct delegation } }
Root cause:Misunderstanding that secondary constructors must delegate to the primary constructor to ensure proper initialization.
#2Using secondary constructors to provide default values when default parameters suffice.
Wrong approach:class Person(val name: String, val age: Int) { constructor(name: String) : this(name, 0) // unnecessary secondary constructor }
Correct approach:class Person(val name: String, val age: Int = 0) // simpler with default parameter
Root cause:Not knowing Kotlin supports default parameter values directly in primary constructors.
#3Creating ambiguous secondary constructors with overlapping parameter types.
Wrong approach:class Person { constructor(name: String) : this(name, 0) constructor(age: Int) : this("Unknown", age) constructor(name: String, age: Int) { } }
Correct approach:class Person(val name: String, val age: Int) { constructor(name: String) : this(name, 0) constructor(age: Int) : this("Unknown", age) }
Root cause:Overlapping parameter types cause compiler confusion; careful design avoids ambiguous calls.
Key Takeaways
Secondary constructors provide alternative ways to create objects but must always delegate to the primary constructor.
They offer flexibility for different initialization scenarios but are often replaceable by default parameters or factory methods.
Understanding constructor delegation ensures consistent and safe object initialization.
Secondary constructors compile into multiple JVM constructor methods, adding minimal overhead.
Choosing between secondary constructors, default parameters, and factory methods depends on clarity, flexibility, and design needs.

Practice

(1/5)
1. What is the main purpose of a secondary constructor in Kotlin?
easy
A. To create static methods
B. To replace the primary constructor completely
C. To provide additional ways to create an object with different parameters
D. To define functions inside a class

Solution

  1. Step 1: Understand constructors in Kotlin

    Kotlin classes can have a primary constructor and one or more secondary constructors to create objects.
  2. Step 2: Role of secondary constructors

    Secondary constructors allow creating objects with different sets of parameters, providing flexibility.
  3. Final Answer:

    To provide additional ways to create an object with different parameters -> Option C
  4. Quick Check:

    Secondary constructors = multiple ways to create objects [OK]
Hint: Secondary constructors add extra ways to create objects [OK]
Common Mistakes:
  • Thinking secondary constructors replace the primary constructor
  • Confusing constructors with functions
  • Assuming secondary constructors create static methods
2. Which of the following is the correct syntax for a secondary constructor in Kotlin?
easy
A. secondary constructor(name: String) { this.name = name }
B. fun constructor(name: String) { this.name = name }
C. init constructor(name: String) { this.name = name }
D. constructor(name: String) { this.name = name }

Solution

  1. Step 1: Recall Kotlin secondary constructor syntax

    Secondary constructors use the keyword constructor followed by parameters and a body.
  2. Step 2: Check each option

    constructor(name: String) { this.name = name } uses correct syntax: constructor(name: String) { ... }. Others use invalid keywords.
  3. Final Answer:

    constructor(name: String) { this.name = name } -> Option D
  4. Quick Check:

    Keyword 'constructor' starts secondary constructors [OK]
Hint: Look for 'constructor' keyword without fun or init [OK]
Common Mistakes:
  • Adding 'fun' before constructor
  • Using 'secondary' keyword
  • Confusing with init blocks
3. What will be the output of the following Kotlin code?
class Person(val name: String) {
    var age: Int = 0
    constructor(name: String, age: Int) : this(name) {
        this.age = age
    }
}

fun main() {
    val p = Person("Alice", 30)
    println("Name: ${p.name}, Age: ${p.age}")
}
medium
A. Name: Alice, Age: 0
B. Name: Alice, Age: 30
C. Name: , Age: 30
D. Compilation error

Solution

  1. Step 1: Understand constructor calls

    The secondary constructor calls the primary constructor with this(name), initializing name.
  2. Step 2: Assign age in secondary constructor

    The secondary constructor sets this.age = age, so age becomes 30.
  3. Final Answer:

    Name: Alice, Age: 30 -> Option B
  4. Quick Check:

    Secondary constructor sets age correctly [OK]
Hint: Secondary constructor calls primary, then sets extra properties [OK]
Common Mistakes:
  • Assuming age stays 0
  • Thinking name is empty
  • Expecting compilation error
4. Identify the error in this Kotlin class with a secondary constructor:
class Car(val model: String) {
    constructor(model: String, year: Int) {
        println("Year: $year")
    }
}
medium
A. Secondary constructor must call the primary constructor
B. Cannot assign to val property 'model'
C. Missing return type in secondary constructor
D. println cannot be used inside constructor

Solution

  1. Step 1: Check secondary constructor rules

    In Kotlin, a secondary constructor must delegate to the primary constructor using : this(...).
  2. Step 2: Analyze given code

    The secondary constructor does not call this(model), so it violates the rule.
  3. Final Answer:

    Secondary constructor must call the primary constructor -> Option A
  4. Quick Check:

    Secondary constructors require delegation [OK]
Hint: Always delegate secondary constructors to primary with ': this(...)' [OK]
Common Mistakes:
  • Forgetting to delegate to primary constructor
  • Trying to assign val property directly
  • Thinking println is disallowed
5. You want to create a Kotlin class Book with a primary constructor that takes title and a secondary constructor that also takes author. The secondary constructor should reuse the primary constructor and set author. Which code correctly implements this?
hard
A. class Book(val title: String) { var author: String = "Unknown" constructor(title: String, author: String) : this(title) { this.author = author } }
B. class Book(val title: String, var author: String) { constructor(title: String) { this.title = title this.author = "Unknown" } }
C. class Book(val title: String) { constructor(title: String, author: String) { this.title = title this.author = author } }
D. class Book { constructor(title: String) { this.title = title } constructor(title: String, author: String) { this.title = title this.author = author } }

Solution

  1. Step 1: Check primary constructor and property initialization

    class Book(val title: String) { var author: String = "Unknown" constructor(title: String, author: String) : this(title) { this.author = author } } defines primary constructor with title and a mutable author property with default value.
  2. Step 2: Verify secondary constructor delegates properly

    The secondary constructor calls : this(title) to reuse primary constructor and sets author inside its body.
  3. Final Answer:

    class Book(val title: String) { var author: String = "Unknown" constructor(title: String, author: String) : this(title) { this.author = author } } -> Option A
  4. Quick Check:

    Secondary constructor delegates and sets extra property [OK]
Hint: Secondary constructors must delegate and set extra properties inside body [OK]
Common Mistakes:
  • Not delegating secondary constructor to primary
  • Trying to assign val properties
  • Missing property initialization
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard