Classes and Objects are the central concepts in any Object Oriented Programming(OOP) language.
A class is a blueprint/template for creating objects of similar type. The objects contain state in the form of member variables (properties) and behavior in the form of member functions (methods).
Classes
You can create a Class in Kotlin using the class
keyword -
class Person {
}
The curly braces can be omitted if the class has no body -
class Person
This is the simplest class that you can have in Kotlin. You can create an object/instance of the above the class using its default constructor like so -
val person = Person()
Notice that, unlike other object-oriented programming languages like Java, You don’t need to use the new
keyword to instantiate a class in Kotlin. In fact, new
is not a keyword in Kotlin.
Properties
An empty class is not that useful in real world. Let’s add some properties to our class now.
You can declare properties (member variables) in the class body similar to how you declare any other variable in Kotlin. These properties can be declared as mutable, using the var
keyword or read-only using the val
keyword -
class Person {
// Properties or Member Variables
var firstName: String
var lastName: String
}
In the above class, we have declared two mutable properties. Note that, the code above won’t compile because we haven’t specified how these properties will get initialized when we create an object of the class.
We can provide default values to the properties to avoid compilation error like so -
class Person {
var firstName: String = "Guest"
var lastName: String = ""
}
But for initializing them to different values while creating an object, we need to define a constructor in the class.
Constructors
A constructor is a special kind of member function that is used to initialize the state/properties of newly created objects of the class. It is invoked when you create an instance of the class.
Every class needs to have a constructor. If you don’t declare one yourself, the compiler generates a default constructor.
There are two types of constructors in Kotlin -
- Primary Constructor
- Secondary Constructor
A Kotlin class can have one Primary constructor and one or more secondary constructors.
1. Primary Constructor
The Primary constructor is part of the class header and declared after the class name like so -
class Person constructor(firstName: String, lastName: String) {
}
It takes a list of comma-separated parameters with their type modifiers. These parameters are used to initialize the member variables of the class.
You can omit the constructor
keyword from the primary constructor if it does not have any annotations or visibility modifiers (public
, private
or protected
) -
class Person(firstName: String, lastName: String) {
}
Initializer Block
Let’s now see how to initialize the properties of a class with the parameters passed to the primary constructor.
The primary constructor cannot contain any code. So all the initialization logic is written inside an initializer block which is prefixed with the init
keyword -
class Person(_firstName: String, _lastName: String) {
// Member Variables (Properties) of the class
var firstName: String
var lastName: String
// Initializer Block
init {
this.firstName = _firstName
this.lastName = _lastName
println("Initialized a new Person object with firstName = $firstName and lastName = $lastName")
}
}
I have prefixed the parameter names in the primary constructor with an underscore(_
) to distinguish them from the member variables of the class. It’s not required though, since we’re using this
keyword anyway in the init
block.
Note that, instead of initializing the properties in the init
block, you can directly initialize them in the class body itself like this -
class Person (_firstName: String, _lastName: String) {
// Member Variables (Properties) of the class
var firstName: String = _firstName
var lastName: String = _lastName
// Initializer Block
init {
println("Initialized a new Person object with firstName = $firstName and lastName = $lastName")
}
}
You can create an instance of the above class using the primary constructor like this -
val p = Person("Jack", "Dorsey")
Kotlin’s concise syntax for declaring and initializing properties
Kotlin has a concise syntax for declaring properties and initializing them from the primary constructor -
class Person(var firstName: String, var lastName: String) {
// Initializer Block
init {
println("Initialized a new Person object with firstName = $firstName and lastName = $lastName")
}
}
The above class is equivalent to the class we saw in the previous section.
That’s really cool no? This syntax allows us to directly declare properties inside the primary constructor using the var
or val
keyword, and also frees us from writing the initialization boilerplate code.
Default Values in the Constructor
We can also provide default values for the properties of the class right inside the constructor -
class Person(var firstName: String = "Guest", var lastName: String = "") {
// Initializer Block
init {
println("Initialized a new Person object with firstName = $firstName and lastName = $lastName")
}
}
This allows us to omit the firstName
and lastName
parameters while creating an object. So all of the following calls are valid now -
val person1 = Person("Jack", "Dorsey")
val person2 = Person("Jack")
val person3 = Person()
The default value for a parameter is used if no value is supplied for that parameter while instantiating an object.
2. Secondary Constructor
Apart from the primary constructor, you can also declare one or more secondary constructors in the class. Secondary constructors are prefixed with the constructor
keyword and declared inside the class body -
class Person {
// Properties
var firstName: String
var lastName: String
// Secondary Constructor
constructor(firstName: String, lastName: String) {
this.firstName = firstName
this.lastName = lastName
}
}
You can also combine both primary constructor and secondary constructor in the same class. One thing to note here is that every secondary constructor must call the primary constructor, either directly or indirectly via another secondary constructor.
In the following example, we have declared a primary constructor as well as a secondary constructor. The secondary constructor calls the primary constructor using this
keyword -
class Person(var firstName: String, var lastName: String) {
var age: Int? = null
// Secondary Constructor
constructor(firstName: String, lastName: String, age: Int): this(firstName, lastName) {
this.age = if(age > 0) age else throw IllegalArgumentException("Age must be greater than zero")
}
}
You can now instantiate an object either using the primary constructor or the secondary constructor -
// Calls the primary constructor (Age will be null in this case)
val person1 = Person("Bill", "Gates")
// Calls the secondary constructor
val person2 = Person("Jeff", "Bezos", 53)
You can also have multiple overloaded secondary constructors in the class -
class Person(var firstName: String, var lastName: String) {
var age: Int? = null
var phoneNumber: String? = null
// Secondary Constructor
constructor(firstName: String, lastName: String, age: Int): this(firstName, lastName) {
this.age = if(age > 0) age else throw IllegalArgumentException("Age must be greater than zero")
}
// Secondary Constructor
constructor(firstName: String, lastName: String, age: Int, phoneNumber: String):
this(firstName, lastName, age) {
this.phoneNumber = phoneNumber
}
}
Notice how the last secondary constructor calls the first one using this
keyword.
Visibility Modifiers
Visibility modifiers help us restrict the accessibility of classes, objects, constructors, functions or properties.
There are four types of visibility modifiers in Kotlin - public
, private
, protected
and internal
. The default visibility for everything is public
.
Following are the access scope of these visibility modifiers -
public - Anything that is declared
public
is accessible everywhere.private - A top-level function or class that is declared
private
can be accessed only within the file where it is declared.Any member function, constructor, or property that is declared
private
is visible only within the class where it is declared.protected - Any property or function declared as
protected
is accessible in the same class and its subclasses.internal - Accessible within the same module. A module is a set of files compiled together (ex - a maven project or a gradle module)
Accessing and Setting Properties
Unlike Java, we don’t need to define getters and setters for getting and setting the properties of an object.
Kotlin automatically generates an implicit getter and a setter for mutable properties, and a getter (only) of read-only properties.
You can access the properties of an object using the dot(.
) notation like this -
val person = Person("Sundar", "Pichai")
println(person.firstName) // Sundar
println(person.lastName) // Pichai
For setting properties, just assign them to the new value -
val person = Person("Steve", "Wozniak")
person.lastName = "Jobs"
println("Name = ${person.firstName} ${person.lastName}") // Steve Jobs
Notice that, In Kotlin, we don’t need to call the getter and setter methods for accessing and setting the properties - as we do in Java. Kotlin internally calls the default (implicit) getters/setters of the properties. So the line person.lastName = "Jobs"
in Kotlin is same as person.setLastName("Jobs")
in Java.
Let’s see another example with read-only properties -
class Student (val rollNumber: Int,
val name: String)
val student = Student(1, "John")
println(student.rollNumber)
println(student.name)
student.name = "Jack" // Error: Val can not be assigned
As expected, Kotlin disallows assignment to val
(read-only) properties.
Conclusion
That’s all folks. In this article, you learned the basics of Kotlin classes, objects, primary constructors, secondary constructors and initializer blocks.
Thanks for reading. Stay tuned for more articles on Kotlin.