Primary and Secondary Constructors in Kotlin

Primary and Secondary Constructors in Kotlin

Before starting, let’s think of a situation where you and your friend are walking on a road and somebody calls you by your name. What will you do? You will immediately turn back and respond. This is called Constructor . Here you are the class, with your name as the class name. Whenever someone calls you, with your name, you respond immediately. So, a Constructor is something that is called just after the creation of object i.e. whenever you are called by your name you will respond and this responding is the work that the constructor does.

So, in this blog, we will learn about constructors in Kotlin. We will cover Primary Constructors , init() block and Secondary Constructors . So, let’s get started.

What are Constructors?

Before moving on to constructors, let’s take an example, suppose there is a class named Person, then the properties of the class will be the name of the person, age of the person, the salary of the person, etc.

So, properties are those things which help to identify you. For example, a person is identified by his name, age or place of living. There can be more than one property of a class and all of these properties must be initialized when an object is created and in order to initialize the properties of an object, we use Constructors.

A constructor is a type or kind of member function, which is used to initialize the properties of a class. Whenever you create an object of a class, then the constructor will be called first automatically and after that other methods will be called(on function call).

Let's have an example, to understand it in a better way. Suppose you go to a Grocery shop and buy something and paid the bill. At this time, what you will expect from the shopkeeper is a carry bag. So, carry bag is a property here. Not only for you, everyone coming to the shop and buying something should get a carry bag. So, this step should be called automatically whenever a coustomer buys something. So, the activities that should be done whenever an object is created is put into the constructor and those activities include initialization of properties.

So, every class must have a constructor. If you are not defining the constructor, then the compiler will add constructor known as default constructor .

Unlike Java, or any other object-oriented language, Kotlin has two types of constructor:

  1. Primary Constructor
  2. Secondary Constructor

But it is not necessary to add secondary constructor also. You can have one or both constructors at a time.

Primary Constructor

Unlike Java, you need not declare a constructor in the body of the class. Yeah, you read it right and this property should also be there in Java because writing the same name two times, one for the class name and then again for the constructor is not a good thing :) Anyways, jokes apart.

In Kotlin, you can declare the constructor in the class header itself:

class Person constructor(name: String, age: Int, salary: Int) {
}

Just like functions or methods, it takes a series of parameters with their type. These parameters initialize the variables present in the class.

If you are not having any annotations or modifiers(public, private, protected), then you can omit the constructor keyword like this:

class Person (name: String, age: Int, salary: Int) {
}

By removing the constructor keyword, our code gets simplified and easy to understand.

Initializer Block

So, we have seen that primary constructor is used to initialize the member variables of a class. But we are not writing any code of initialization in the primary constructor, then how will our goal be achieved?

To achieve this task, we use an initializer block called init() to initialize the member variables with the constructor variables. This init() block is executed just after the creation of an object.

class Person(_name: String, _age: Int, _salary: Int) {
    // Member Variables (Properties) of the class
    var name: String
    var age: Int 
    var salary: Int 

    // Initializer Block
    init {
        this.name = _name
        this.age = _age 
        this.salary = _salary 
       println("Initialized a new Person object with Name = $name , age = $age and salary = $salary")
    }
}

this keyword is used to refer to the variables of the class or any block. If you have the same variable name in the class property and in the constructor then by using this keyword you can remove the confusion of the compiler. If you are not using this keyword then your code will look like name = name. So, it is not clear that which name is referenced here. So, to avoid confusion, we use this keyword.

If you don't want to use this keyword, then you can initialize the variables of the class as follows:

class Person(_name: String, _age: Int, _salary: Int) {
    var name: String
    var age: Int
    var salary: Int
    init() {
    println("Initialized a new Person object with name = $name , age = $age and salary = $salary")
    }
}

To create an instance of the Person class, you can use the following code:

val per = Person("Anonymous", 20, 50000)

As soon as the instance of the class is created, the constructor of thr class will be called. In the above example, "Anonymous" will be passed as _name , 20 will be pass as _age and 50000 will be passed as _salary .

Default values in constructor

You need not pass all the parameters while declaring an object. You can put default values to parameters of the constructor as shown below:

class Person(var name: String = "Anonymous", var age: Int = 0, var salary: Int = 20000) {
    // Initializer Block
    init {
        println("Initialized a new Person object with name = $name , age = $lastName" and salary = $salary)
    }
}

Now, the following calls are valid:

//all the 3 values are passed
val person1 = Person("Pubg", 25, 100000) 
//update name and take the default value of age and salary
val person2 = Person("John")
//take all default value
val person3 = Person()

Secondary Constructor

You can use one another constructor along with the primary constructor in Kotlin. Yeah, that's a cool feature of Kotlin.

To do so you need to declare a secondary constructor using the constructor keyword.

class Student (var name: String) {
    init() {
        println("Student has got a name as $name")
    }

    constructor(sectionName: String, id: Int) this(sectionName) {

    }
}

Note: You must call the primary constructor from the secondary constructor explicitly. Also, the property of the class can’t be declared inside the secondary constructor. For example, you can't declare id as the property of the class in the secondary constructor:

class Student (var name: String) {
    init() {
        println("Student has got a name as $name")
    }
    //this will give an error because here we are declaring a property id of the class in the secondary constructor, which is not allowed 
    constructor(sectionName: String, var id: Int) this(sectionName) {

    }
}

If you want to use some property inside the secondary constructor, then declare the property inside the class and use it in the secondary constructor. By doing so, the declared variable will not be accessed inside the init() block. Can you guess the reason???

class Student (var name: String) {

    var id: Int = -1
    init() {
        println("Student has got a name as $name")
    }
    
    constructor(secname: String, id: Int) this(secname) {
        this.id = id
    }
}

Yes, you are right. You can't access the declared variable inside the init() block because the init() block is called just after the primary constructor is called and the primary constructor is called just after the creation of object and all the member variables and member function are created/declared/called after the primary constructor or you can simply say constructor. So, the variable will be declared after the execution of init() block.

Summary

So, in this blog, we learned how to use the use of constructors in Kotlin. Also, we looked upon the types of Constructor i.e. Primary and Secondary Constructor. We learned that the primary constructor uses init() block for its execution, while if you are using Secondary Constructor, then you must have to call Primary Constructor explicitly.

Hope you like this blog :)

Keep learning!

Team MindOrks