Constructors provides us a way to initialise the attributes of the class while an object is created.
There are two types of Constructor in Kotlin:
Let us see them in detail.
To understand Primary Constructor better, let us take the example from the previous tutorial.
class Human{ var name: String = "" var food: String = "" var language: String = "" fun eat(){ println(name+" Eats "+food) } fun speak(){ println(name+" Speaks "+language) } } fun main() { var human1 = Human() human1.name = "John" human1.food = "Burger" human1.language = "English" var human2 = Human() human2.name = "Rakhi" human2.food = "Rice" human2.language = "Hindi" human1.eat() human1.speak() human2.eat() human2.speak() }
Now, let us see, how can we rewrite the above example using the Primary Constructor.
class Human(var name: String, var food: String, var language: String) { fun eat(){ println(name+" Eats "+food) } fun speak(){ println(name+" Speaks "+language) } } fun main() { var human1 = Human("John", "Burger", "English") var human2 = Human("Rakhi", "Rice", "Hindi") human1.eat() human1.speak() human2.eat() human2.speak() }
In the above code we have used the Primary Constructor.
And with the use of Primary Constructor, the class declaration becomes short.
In simple words, the below Primary Constructor definition is,
class Human(var name: String, var food: String, var language: String) { }
Is somewhat equivalent to,
class Human { var name: String = "" var food: String = "" var language: String = "" }
So, you can say, in a Primary Constructor the properties, name, food and language is declared in one line.
class Human(var name: String, var food: String, var language: String)
So, while we declare the class, the Constructor is also declared at that point of time.
class Human(var name: String, var food: String, var language: String) { ... }
The Constructor starts with a parenthesis ( after the class name followed by the properties of the class (i.e. var name: String, var food: String, var language: String).
And thats all. Your Constructor is ready for use.
Now, when we try creating an Object of Human class i.e. human1,
var human1 = Human("John", "Burger", "English")
All we have done is, while creating the object human1, we have passed the values, "John", "Burger" and "English" as Arguments.
human1 = Human("John", "Burger", "English")
And what happens is, the primary constructor,
'class Human(var name: String, var food: String, var language: String)'
is called.
And the values are initialised to the properties of the class.
And "John" gets initialised to the variable name, "Burger" to food and "English" to the variable language.
And we get the human1 object with the values.
Similarly, human2 object is initialised,
var human2 = Human("Rakhi", "Rice", "Hindi")
And eat() and speak() prints the desired output.
human1.eat() human1.speak() human2.eat() human2.speak()
So, far we have seen, how can we create a Primary Constructor with the class properties defined in it.
Now, what if, we don't want the class properties to be defined in the Primary Constructor?
And Luckily, Kotlin provides a way to do that as well.
Now, we don't want the class properties to be defined in the Primary Constructor itself.
To achieve that let us modify the above example.
class Human(nameTemp: String, foodTemp: String, languageTemp: String) { var name: String var food: String var language: String init{ name = nameTemp food = foodTemp language = languageTemp } } fun main() { var human1 = Human("John", "Burger", "English") var human2 = Human("Rakhi", "Rice", "Hindi") }
This time we kept our code clean, removing the eat() and speak() method.
So, in the above code, the properties name, food and language are defined inside the class.
var name: String var food: String var language: String
And inside the Primary Constructor we have the arguments, nameTemp, foodTemp and languageTemp.
class Human(nameTemp: String, foodTemp: String, languageTemp: String)
But! Hold on.
How can we say that the Primary Constructor has just arguments?
Look closely, the Arguments of the Primary Constructor, nameTemp, foodTemp and languageTemp doesn't have var keyword before it.
And the properties of the class in the Primary Constructor has var keyword in it.
Now, let us get back to our code. What happens, when we declare human1 object is,
var human1 = Human("John", "Burger", "English")
The values, John, Burger and English gets passed to the arguments nameTemp, foodTemp and languageTemp.
And the values sits in the arguments nameTemp, foodTemp and languageTemp.
So, the values are not yet a part of the human1 Object. They becomes a part of human1 Object in the init block.
init{ name = nameTemp food = foodTemp language = languageTemp }
And
name = nameTemp
Takes the value John from the local variable/argument nameTemp and puts it to the name property/attribute of the Human class.
Similarly, the next two lines,
food = foodTemp language = languageTemp
Assigns the values Burger and English to the food and language attribute of the human1 object.
And the human1 object has the values now.
Similarly, the next line,
var human2 = Human("Rakhi", "Rice", "Hindi")
Assigns the values to the human2 object.
So, in the above example, we have seen how to define a Primary Constructor that can be defined in the easiest way.
Now, what if you need more than one constructor?
In simple words, what if you need a constructor that accepts three argument.
var human1 = Human("Rakhi", "Rice", "Hindi")
And also you need the second constructor that accepts two Arguments.
var human2 = Human("Paul", "Pizza")
In that case we can think of Secondary Constructor(Well! There are other ways as well but let's try fitting in Secondary Constructor in this scenario).
Let us understand Secondary Constructor with the below example.
class Human { var name: String = "" var food: String = "" var language: String = "" constructor(nameTemp: String, foodTemp: String, languageTemp: String) { name = nameTemp food = foodTemp language = languageTemp } constructor(nameTemp: String, foodTemp: String){ name = nameTemp food = foodTemp } } fun main() { var human1 = Human("Rakhi", "Rice", "Hindi") var human2 = Human("Paul", "Pizza") }
So, in the above example, we have two secondary constructors.
The first one is with three arguments,
constructor(nameTemp: String, foodTemp: String, languageTemp: String) { name = nameTemp food = foodTemp language = languageTemp }
And the second one is with two arguments,
constructor(nameTemp: String, foodTemp: String){ name = nameTemp food = foodTemp }
While defining a Secondary Constructor, just remember the below points.
class Human { ... ... constructor(nameTemp: String, foodTemp: String){ name = nameTemp food = foodTemp } }
So, when we call the constructor with three arguments,
var human1 = Human("Rakhi", "Rice", "Hindi")
The three arguments Secondary Constructor is called,
constructor(nameTemp: String, foodTemp: String, languageTemp: String) { name = nameTemp food = foodTemp language = languageTemp }
Similarly, when we call the constructor with two arguments,
var human2 = Human("Paul", "Pizza")
The two arguments Secondary Constructor is called,
constructor(nameTemp: String, foodTemp: String){ name = nameTemp food = foodTemp }
Kotlin gives us the flexibility to call a Constructor from the other constructor.
Let us see with the below example.
class Human { var name: String = "" var food: String = "" var language: String = "" constructor(nameTemp: String, foodTemp: String, languageTemp: String): this("Paul", "Pizza"){ name = nameTemp food = foodTemp language = languageTemp } constructor(nameTemp: String, foodTemp: String){ name = nameTemp food = foodTemp } } fun main() { var human1 = Human("Rakhi", "Rice", "Hindi") }
So, in the above code, we have called the Constructor with two Arguments from the Constructor with three Arguments.
constructor(nameTemp: String, foodTemp: String, languageTemp: String): this("Paul", "Pizza"){ name = nameTemp food = foodTemp language = languageTemp }
And all we have done is used this followed by two arguments,
this("Paul", "Pizza")
this actually refers to the same class. In this case our current class is Human.
So, in other words,
this("Paul", "Pizza")
Is equivalent to,
Human("Paul", "Pizza")