Kotlin Constructors & Initialisers

Kotlin Constructors & Initialisers

Hello there👋, it's been a long time! Hope you are doing good! In the previous blog in this series, we learnt about Classes and today, we shall be learning about something very important about classes and all object-oriented programming languages.

🎈 What are Constructors?

Kotlin1-Constructors.jpg

According to Wikipedia, a constructor is a special type of subroutine called to create an object.

🎈 Constructor Vs Initialiser?

image.png A constructor is a defined method on a type that takes a specified number of parameters and is used to create and initialize an object.

An object initializer is a code that runs on an object after a constructor and can be used to succinctly set any number of fields on the object to specified values.

Read 👉 Stack OverFlow Answers

Constructors are generally used for instantiating an object. The task of constructors is to initialize(assign values) to the data members of the class when an object of the class is created.

In Python the __init__() method is called the constructor and is always called when an object is created. Kotlin constructors and initializer blocks run automatically whenever an instance of an object is created. (note that there's nothing that corresponds to__new__()).

There are two types of constructors in Kotlin:

💨 Primary constructor
💨 Secondary constructor

A Kotlin class may have one primary constructor, whose parameters are supplied after the class name.

The primary constructor parameters are available when you initialize properties in the class body, and also in the optional initializer block, which can contain complex initialization logic (a property can be declared without an initial value, in which case it must be initialized in init).

Also, you'll frequently want to use val instead of var in order to make your properties immutable after construction.

🔸 Primary Constructors & Initialising

The primary constructor is a part of the class header, and it goes after the class name and optional type parameters.

class Person constructor(firstName: String) { /*...*/ }

If the primary constructor does not have any annotations or visibility modifiers, the constructor keyword can be omitted:

class Person(firstName: String) { /*...*/ }

The primary constructor cannot contain any code. Initialization code can be placed in initializer blocks prefixed with the init keyword.

During the initialization of an instance, the initializer blocks are executed in the same order as they appear in the class body, interleaved with the property initializers:

class InitOrderDemo(name: String) {
    val firstProperty = "First property: $name".also(::println)

    init {
        println("First initializer block that prints ${name}")
    }

    val secondProperty = "Second property: ${name.length}".also(::println)

    init {
        println("Second initializer block that prints ${name.length}")
    }
}

Primary constructor parameters can be used in the initializer blocks. They can also be used in property initializers declared in the class body:

class Customer(name: String) {
    val customerKey = name.uppercase()
}

Kotlin has a concise syntax for declaring properties and initializing them from the primary constructor:

class Person(val firstName: String, val lastName: String, var age: Int)

Such declarations can also include default values of the class properties:

class Person(val firstName: String, val lastName: String, var isEmployed: Boolean = true)

You can use a trailing comma when you declare class properties:

class Person(
    val firstName: String,
    val lastName: String,
    var age: Int, // trailing comma
) { /*...*/ }

Much like regular properties, properties declared in the primary constructor can be mutable (var) or read-only (val) but val is usually recommended like I said above

If the constructor has annotations or visibility modifiers, the constructor keyword is required and the modifiers go before it:

class Customer public @Inject constructor(name: String) { /*...*/ }

Learn more about visibility modifiers.

🔸 Secondary constructors & Initialising

A class can also declare secondary constructors, which are prefixed with constructor:

class Person(val pets: MutableList<Pet> = mutableListOf())

class Pet {
    constructor(owner: Person) {
        owner.pets.add(this) // adds this pet to the list of its owner's pets
    }
}

If the class has a primary constructor, each secondary constructor needs to delegate to the primary constructor, either directly or indirectly through another secondary constructor(s).

Delegation to another constructor of the same class is done using the this keyword:

class Person(val name: String) {
    var children: MutableList<Person> = mutableListOf()
    constructor(name: String, parent: Person) : this(name) {
        parent.children.add(this)
    }
}

Code in initializer blocks effectively becomes part of the primary constructor.

Delegation to the primary constructor happens as the first statement of a secondary constructor, so the code in all initializer blocks and property initializers is executed before the body of the secondary constructor.

Even if the class has no primary constructor, the delegation still happens implicitly, and the initializer blocks are still executed:

class Constructors {
    init {
        println("Init block")
    }
​
    constructor(i: Int) {
        println("Constructor $i")
    }
}

If a non-abstract class does not declare any constructors (primary or secondary), it will have a generated primary constructor with no arguments. The visibility of the constructor will be public.

If you don't want your class to have a public constructor, declare an empty primary constructor with non-default visibility:

class DontCreateMe private constructor () { /*...*/ }

🎈Constructors Vs Destructors

image.png The primary purpose of a constructor is to allocate memory to the objects when they are created. As against, the main purpose of a destructor is to deallocate memory of the object when it is destroyed.

A constructor is called when an object is created. In contrast, a destructor is called when a program is terminated or the program exit the block in which an object is created.

I think Kotlin does not have a destructor but inline 
lambdas can be used. We shall look at these more 
in the upcoming chapters in the series.
In Python, destructors are not needed as much needed 
as in other languages like C++ because Python has a 
garbage collector that handles memory management automatically.

The __del__() method is known as a destructor method in Python.

Basically destructors are called when an object gets destroyed.

Conclusion

If you have read up to this far and have enjoyed reading, consider reading more at the official docs and Kindly comment for any issue here.

Follow me here & on Twitter : Subscribe for Alerts!

Ronnie Atuhaire 😎