Why the different primary constructor and init block in Kotlin

Why the different primary constructor and init block in Kotlin

Tarik Guney's photo
Tarik Guney
·Jul 19, 2018·

7 min read

Subscribe to my newsletter and never miss my upcoming articles

Quick Reminder: Don’t forget to subscribe to **my YouTube channel** where you can reach to many up-to-date tutorials on programming languages, frameworks, and my career planing advices.

If you are working with Kotlin, one of the first things that may have come a little odd was probably the way you define constructor functions (ctor). The following code defines a class with a primary ctorand init block:

class InitOrderDemo(name: String) {

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

Reminder: Don’t forget to check out my YouTube channel where I teach various topics on software engineering.

If you are like me, you would probably be asking yourself many “why” questions when learning and using Kotlin. What is it that they tried to accomplish by offering a language construct and syntax like that? I don’t know the exact trail of thoughts passed through the minds of the authors of the language, but I may have a few reasons.

First of all, I don’t interpret the primary and secondaryas the order of importance. They probably could not find a better naming, but that is fine. Most of the time, we use ctorsto make sure the object is initialized properly by leveraging the power of the compiler. We simply say that if the developers don’t pass these data, they cannot use this object. Therefore, primary sounds more like the primary reason you would use a ctor. The primary reason why you would use a constructor: Passing data and initializing the internal state of the object. The secondary ctors come into play when you need more than data storage. Perhaps, you want to apply toLowerString() functions to that Stringparameter.

It is usually a good practice not to perform a big and time-consuming initialization in your ctorfunctions. Especially, when you need to create multiple instances of that class. That’s why we have Singleton Pattern and other Lazyevaluation techniques. Initialize a piece of data when you truly need it. Modern computers run hundreds of applications and services concurrently. Hence, your application is not the only one anymore in a computer. And yes, we don’t have infinite amount of resources in the real-world. Therefore, primary ctor does not accept any logic in it except for just variable initialization. Of course, like every other language feature, a bad programmer will always find a way to abuse them, but a programming language can help to the formation of expectations of a programmer like how the primary ctor does it. When you see it, you know that does not have any logic in it. At this point, you would say “…But we haveinit{} that is run right after the primary constructor...”. When you look closely, you see that these two clearly say different things. init{} says that it is for running logic, whereas, the primary ctor says the otherwise. All the language can do is to show you the path and whether you follow it or not depends on the practices you have developed with your team members. If you use init{} for disgusting practices (sorry, but had to be said), then there is nothing the language can prevent from you. But if you follow the logical separations the language is recommending, then being on the same page with everyone else will help you to write and read code more effectively and efficiently.

I would recommend using init{} for things like logging. Don’t put weird I/O or CPU-bound code there. I won’t say not to use it. That would sound stupid. If it is there, it is to be used. However, the way you use it should be standardized among your team. When you hire a new developer and if you can easily and confidently say that you only use init{} for — let’s say — logging, then you are on the right track. You simply shaped the future expectations of your new friend and helped him tremendously for his future works.

Effectively vs. Efficiently Effectively is to do the right thing. Efficiently is to do something in the best way possible. Combine them!? Brain explodes…!

The primary ctor is right there at the same line of the class definition. That means, you don’t need to scroll down and try to find the location of the primary constructor. That is easier to the eyes when reading. You exactly know what other things a class expects from its consumers.


This column was not about whether the Kotlin is a perfect language or not. My intention was to think about a feature of Kotlin. But, is Kotlin the language you have all been expecting? I am not sure what you have been expecting for all these years, but it is just too early to come to any strong final conclusions. Our demands change, the industry evolves, therefore the languages don’t stay the same. To me, the most important thing about a programming language is whether it is backed up by people who are constantly not satisfied with what their language offers. Also, if you are in the industry for long enough, you must have learned your lesson for not saying always and never.

Share this