Understanding Classes, Objects, and Constructors in Kotlin
Course: Android App Development
Topic: Understanding Classes, Objects, and Constructors
Course Details: Android App Development Training
Demo Registration: Register for a Free Course Demo
JustAcademy Homepage: Visit JustAcademy
1. Introduction to Classes, Objects, and Constructors
Kotlin is a modern programming language widely used for Android application development. It supports object-oriented programming (OOP), which helps developers organize code into reusable units that represent real-world entities such as users, products, students, bank accounts, and mobile devices.
Classes, objects, and constructors are fundamental concepts in Kotlin. A class defines the structure and behavior of an entity, an object is an instance of that class, and a constructor initializes the object with the information it needs.
For example, an Android shopping application may have a Product class containing a product name, price, and stock quantity. Individual products such as a laptop, mobile phone, and headset can be represented by separate objects created from that class.
Learning Objectives
- Understand the purpose and structure of Kotlin classes.
- Learn how to create objects from classes.
- Understand properties and member functions.
- Learn primary and secondary constructors.
- Use constructor parameters, default values, and named arguments.
- Initialize objects using
init blocks.
- Apply classes and objects to Android application scenarios.
- Identify common errors when creating and initializing objects.
2. What Is a Class in Kotlin?
A class is a blueprint or template that defines the properties and functions that its objects can contain. It describes what information an entity stores and what operations it can perform.
In Kotlin, the class keyword is used to declare a class. A class can contain properties, constructors, initializer blocks, member functions, and other declarations.
Basic Syntax
class ClassName {
// Properties
// Constructors
// Member functions
}
Example: Creating a Student Class
class Student {
var name: String = "Unknown"
var age: Int = 0
fun displayDetails() {
println("Name: $name")
println("Age: $age")
}
}
fun main() {
val student = Student()
student.displayDetails()
}
Output
Name: Unknown
Age: 0
In this example, Student is the class name. The name and age properties store information, while displayDetails() is a member function that displays the student's details.
Important Characteristics of Classes
- A class groups related data and behavior together.
- It can be used to create multiple independent objects.
- Properties represent an object's state.
- Member functions represent an object's behavior.
- A class declaration does not automatically create an object unless an instance is constructed or an object declaration is used.
3. What Is an Object?
An object is an instance of a class. It contains its own instance properties and can use the functions defined by its class.
Think of a class as a blueprint for a house. The blueprint describes the structure, while each actual house built from that blueprint is a separate object. Similarly, one Kotlin class can be used to create many objects.
Creating an Object
In Kotlin, an object is generally created by calling the class constructor. Unlike Java, Kotlin does not require the new keyword.
class Mobile {
var brand: String = "Not specified"
var price: Double = 0.0
fun displayInfo() {
println("Brand: $brand")
println("Price: $price")
}
}
fun main() {
val mobile1 = Mobile()
mobile1.brand = "Samsung"
mobile1.price = 25000.0
val mobile2 = Mobile()
mobile2.brand = "OnePlus"
mobile2.price = 30000.0
mobile1.displayInfo()
mobile2.displayInfo()
}
Output
Brand: Samsung
Price: 25000.0
Brand: OnePlus
Price: 30000.0
Both objects are created from the same Mobile class, but each stores its own brand and price values.
Accessing Object Properties and Functions
The dot operator (.) is used to access accessible properties and member functions of an object.
val student = Student()
student.name = "Aarav"
student.age = 21
student.displayDetails()
Here, student.name accesses the name property, while student.displayDetails() calls the function belonging to that object.
4. Difference Between a Class and an Object
| Class |
Object |
| A blueprint defining structure and behavior. |
An instance created from a class. |
| Defines properties and functions. |
Stores instance-specific property values and uses class functions. |
Declared using the class keyword. |
Usually created by calling a constructor. |
| Can be used to create many objects. |
Represents one particular instance. |
Example: class Student. |
Example: val student = Student(). |
5. Understanding Properties and Member Functions
Properties and member functions are two important parts of a class. Properties hold information about an object, while functions define the operations that the object can perform.
5.1 Properties
Kotlin uses val and var to declare properties. A val property is read-only after initialization, while a var property can be reassigned.
class Employee {
val employeeId: Int = 101
var employeeName: String = "Neha"
var salary: Double = 35000.0
}
In this example, employeeId cannot be reassigned after initialization, but employeeName and salary can be changed.
5.2 Member Functions
Member functions are declared inside a class and describe the behavior of its objects.
class BankAccount {
var balance: Double = 0.0
fun deposit(amount: Double) {
if (amount > 0) {
balance += amount
}
}
fun showBalance() {
println("Current balance: $balance")
}
}
fun main() {
val account = BankAccount()
account.deposit(5000.0)
account.showBalance()
}
Output
Current balance: 5000.0
The deposit() function changes the account balance, while showBalance() displays it. In a real banking application, additional validation, transaction handling, and security controls would be necessary.
6. What Is a Constructor?
A constructor is a special part of a class declaration used when creating an object. It accepts the information needed to initialize the object and helps establish a valid initial state.
For example, a Product object may require a product name and price. A constructor allows those values to be supplied when the object is created instead of creating an object with incomplete information and assigning the values later.
Why Constructors Are Important
- They initialize objects with appropriate values.
- They reduce repetitive property assignments.
- They allow required data to be supplied during object creation.
- They can help validate input before an object is used.
- They make classes easier to reuse and test.
7. Primary Constructor in Kotlin
A primary constructor is declared in the class header, immediately after the class name. It is a concise way to accept initialization parameters and optionally declare properties.
Basic Syntax
class ClassName(parameter1: Type, parameter2: Type)
Example
class Student(
val name: String,
val age: Int
)
fun main() {
val student1 = Student("Aarav", 20)
val student2 = Student("Meera", 22)
println(student1.name)
println(student2.name)
}
Output
Aarav
Meera
The Student class declares a primary constructor with two parameters. Because both parameters use val, Kotlin also declares read-only properties named name and age.
Constructor Parameters With and Without Properties
A constructor parameter declared with val or var becomes a property. A parameter without either keyword is not automatically stored as a property, although it can be used during initialization.
class User(val username: String, age: Int) {
val userAge: Int = age
fun display() {
println("Username: $username")
println("Age: $userAge")
}
}
fun main() {
val user = User("riya_dev", 24)
user.display()
}
Here, username is a property declared in the constructor. The age parameter is used to initialize userAge, which is the stored property available later.
8. Default Constructor and Default Parameter Values
If a class declares no constructor, Kotlin provides an implicit no-argument primary constructor when the class declaration permits it. You can also define a primary constructor with default parameter values so objects can be created with fewer arguments.
Example: Default Values
class Mobile(
val brand: String = "Unknown",
val price: Double = 0.0
)
fun main() {
val mobile1 = Mobile()
val mobile2 = Mobile("Samsung", 25000.0)
println(mobile1.brand)
println(mobile2.brand)
}
Output
Unknown
Samsung
The first object uses the default values. The second object receives custom values. Default arguments help keep code concise when many objects share common initial settings.
9. Named Arguments in Constructors
Named arguments let you specify constructor parameters by name rather than relying only on their position. They improve readability, particularly when several parameters have the same data type.
class Product(
val name: String,
val price: Double,
val inStock: Boolean
)
fun main() {
val product = Product(
name = "Wireless Headphones",
price = 1999.0,
inStock = true
)
println(product.name)
println(product.price)
println(product.inStock)
}
Named arguments make it clear which value belongs to each parameter and reduce confusion when creating complex objects.
10. Secondary Constructors
A secondary constructor provides an additional way to create an instance of a class. It is declared inside the class body using the constructor keyword.
Secondary constructors can be useful when a class needs to accept different input formats or support different initialization paths. If a class already has a primary constructor, each secondary constructor must delegate to it, directly or indirectly.
Example
class Employee(val name: String, val salary: Double) {
constructor(name: String) : this(name, 25000.0)
}
fun main() {
val employee1 = Employee("Amit", 40000.0)
val employee2 = Employee("Priya")
println("${employee1.name}: ${employee1.salary}")
println("${employee2.name}: ${employee2.salary}")
}
Output
Amit: 40000.0
Priya: 25000.0
The primary constructor accepts both a name and salary. The secondary constructor accepts only a name and delegates to the primary constructor with a default salary.
Primary Constructor vs. Secondary Constructor
| Primary Constructor |
Secondary Constructor |
| Declared in the class header. |
Declared inside the class body. |
| Provides the main initialization path. |
Provides an additional initialization path. |
| Does not contain a regular constructor body. |
Can contain a constructor body. |
Can declare properties using val or var. |
Parameters do not automatically become properties. |
| Only one primary constructor is allowed. |
A class can have multiple secondary constructors when their signatures are distinct. |
11. Initializer Blocks Using init
The init block contains code that runs during object initialization. It is useful when initialization requires validation or additional logic beyond assigning constructor parameters.
Example: Validating a Product Price
class Product(
val name: String,
val price: Double
) {
init {
require(name.isNotBlank()) {
"Product name cannot be empty"
}
require(price >= 0) {
"Price cannot be negative"
}
}
}
fun main() {
val product = Product("Keyboard", 1499.0)
println(product.name)
}
The require() function throws an IllegalArgumentException if its condition is false. This prevents the application from accepting invalid values through this constructor.
Initialization Order
- Primary constructor parameters are made available during initialization.
- Property initializers and
init blocks execute in the order they appear in the class body.
- Secondary constructors delegate to the primary constructor before executing their own bodies.
- Initialization should avoid depending on properties that have not yet been initialized.
12. Using this in Constructors and Classes
The keyword this refers to the current object. In a secondary constructor, this(...) delegates to another constructor of the same class. Inside member functions, this can clarify that a property belongs to the current instance.
class Customer(val name: String) {
var city: String = "Not specified"
fun updateCity(city: String) {
this.city = city
}
fun display() {
println("$name lives in $city")
}
}
fun main() {
val customer = Customer("Ananya")
customer.updateCity("Mumbai")
customer.display()
}
Output
Ananya lives in Mumbai
In this.city = city, the left side refers to the object's property and the right side refers to the function parameter.
13. Data Classes and Regular Classes
Kotlin provides data classes for objects primarily used to hold data. They can automatically generate useful methods such as equals(), hashCode(), toString(), and copy() for properties declared in the primary constructor.
data class UserProfile(
val id: Int,
val name: String,
val email: String
)
fun main() {
val user1 = UserProfile(1, "Riya", "[email protected]")
val user2 = user1.copy(email = "[email protected]")
println(user1)
println(user2)
}
A regular class is suitable when you need custom behavior or do not want data-class-generated equality and copy behavior. A data class is convenient for data models, such as profile information returned by an API.
14. Classes and Objects in Android Development
Android applications use classes and objects to organize application logic, represent data, manage UI state, and communicate with services. For example, a learning application might use classes for courses, students, lessons, and enrollment records.
Example: Course Model
data class Course(
val id: Int,
val title: String,
val durationInWeeks: Int,
val fee: Double
) {
fun displayCourse(): String {
return "$title - $durationInWeeks weeks"
}
}
fun main() {
val course = Course(
id = 101,
title = "Android App Development",
durationInWeeks = 12,
fee = 15000.0
)
println(course.displayCourse())
}
Output
Android App Development - 12 weeks
This model can represent course information used by an Android screen, repository, or API layer. In a real application, data models are commonly combined with other architectural components rather than handling every responsibility themselves.
Example: Representing a User Profile
data class User(
val userId: String,
val fullName: String,
val email: String
)
fun main() {
val user = User(
userId = "U1001",
fullName = "Karan Sharma",
email = "[email protected]"
)
println("Welcome, ${user.fullName}")
}
In an Android project, a user object can supply information to a profile screen. The UI layer can read the object's properties and display the user's name and email.
15. Object Declarations and Singleton Objects
Kotlin also supports the object keyword for declaring a singleton: an object that is created once and accessed through its declared name. This differs from creating multiple instances of an ordinary class.
object AppConfig {
const val APP_NAME = "Learning App"
fun showAppName() {
println(APP_NAME)
}
}
fun main() {
AppConfig.showAppName()
}
This pattern can be useful for stateless shared configuration or utility behavior. Avoid placing mutable user-specific or screen-specific state in a global singleton unless its lifecycle and concurrency behavior are deliberately managed.
16. Encapsulation and Safe Object Design
Encapsulation means grouping data and related behavior together while controlling how the internal state can be accessed or modified. Constructors and access modifiers help create objects that maintain valid state.
Example
class BankAccount(initialBalance: Double) {
var balance: Double = initialBalance
private set
init {
require(initialBalance >= 0) {
"Initial balance cannot be negative"
}
}
fun deposit(amount: Double) {
require(amount > 0) {
"Deposit must be positive"
}
balance += amount
}
}
fun main() {
val account = BankAccount(1000.0)
account.deposit(500.0)
println(account.balance)
}
The private setter prevents callers from assigning an arbitrary balance directly. The class instead exposes a controlled operation for deposits. A production financial system would need additional security, persistence, and transaction controls.
17. Common Errors and Troubleshooting
| Problem |
Cause |
Solution |
| Too many arguments for constructor |
The number of supplied arguments does not match an available constructor. |
Check the constructor signature and supplied values. |
| No value passed for a parameter |
A required parameter was omitted. |
Supply the value or define an appropriate default. |
| Unresolved reference |
A property or function name is incorrect or out of scope. |
Verify spelling, visibility, and object access. |
| Val cannot be reassigned |
Code attempts to assign a new value to a read-only property. |
Use a suitable var when mutation is genuinely required. |
| Invalid constructor input |
The supplied values violate the class's rules. |
Validate inputs using require() or appropriate domain logic. |
| Confusing constructor overloads |
Multiple constructors accept similar argument types. |
Prefer a clear primary constructor, default arguments, or named arguments. |
| Secondary constructor delegation error |
A secondary constructor does not delegate correctly. |
Ensure it calls another constructor using this(...). |
18. Best Practices for Classes and Constructors
- Use meaningful class names such as
Student, Product, and UserProfile.
- Follow PascalCase for class names and camelCase for properties and functions.
- Prefer
val for properties that do not need reassignment.
- Use primary constructors for straightforward object initialization.
- Use default arguments and named arguments to improve readability.
- Use secondary constructors only when they provide a clear additional initialization path.
- Validate required values during initialization.
- Keep each class focused on a clear responsibility.
- Use data classes for models that primarily represent data.
- Avoid exposing mutable internal state unnecessarily.
- Test valid and invalid constructor inputs.
- Keep Android UI logic, data models, and data-access responsibilities appropriately separated.
19. Practical Exercises
Exercise 1: Create a Student Class
- Create a class named
Student.
- Add properties for student ID, name, and course.
- Initialize the properties using a primary constructor.
- Create two student objects and display their information.
Exercise 2: Build a Product Class
- Create a
Product class with a name, price, and stock quantity.
- Use an
init block to reject negative prices and stock quantities.
- Create objects using named arguments.
- Write a member function that displays product details.
Exercise 3: Use Secondary Constructors
- Create an
Employee class with a name and salary.
- Define a primary constructor that accepts both values.
- Add a secondary constructor that accepts only the employee name and supplies a default salary.
- Create objects using both constructors.
Exercise 4: Android Course Model
- Create a
Course data class with course ID, title, duration, and fee.
- Create at least three course objects.
- Display each course's details.
- Use the
copy() function to create an updated course object.
20. Mini Project: Student Registration Model
Build a simple Kotlin console program that represents students registering for an Android development course. This exercise focuses on constructors, object creation, properties, and validation before integrating similar models into an Android UI.
data class Student(
val studentId: Int,
val name: String,
val courseName: String,
val email: String
) {
init {
require(studentId > 0) {
"Student ID must be positive"
}
require(name.isNotBlank()) {
"Student name cannot be empty"
}
require(email.contains("@")) {
"Enter a valid email address"
}
}
fun displayDetails() {
println("Student ID: $studentId")
println("Name: $name")
println("Course: $courseName")
println("Email: $email")
}
}
fun main() {
val student = Student(
studentId = 101,
name = "Ananya Patil",
courseName = "Android App Development",
email = "[email protected]"
)
student.displayDetails()
}
Expected Output
Student ID: 101
Name: Ananya Patil
Course: Android App Development
Email: [email protected]
Project Learning Outcomes
- Define a Kotlin data class with a primary constructor.
- Create objects using named arguments.
- Validate data during initialization.
- Use a member function to display object details.
- Understand how model objects can support an Android registration workflow.
21. Interview Questions and Answers
Q1. What is a class in Kotlin?
Answer: A class is a blueprint that defines properties and functions used by its objects.
Q2. What is an object?
Answer: An object is an instance of a class with its own instance-specific state.
Q3. What is a constructor?
Answer: A constructor is used when creating an object and establishes its initial state.
Q4. What is a primary constructor?
Answer: A primary constructor is declared in the class header and provides the main initialization parameters.
Q5. What is a secondary constructor?
Answer: A secondary constructor is declared inside the class body and provides an additional way to initialize an instance.
Q6. What is the purpose of an init block?
Answer: An init block runs during object initialization and is often used for validation or setup logic.
Q7. What is the difference between val and var in a constructor?
Answer: A constructor parameter declared with val becomes a read-only property, while one declared with var becomes a mutable property.
Q8. Does Kotlin require the new keyword to create an object?
Answer: No. An instance is created by calling the class constructor, such as Student("Aarav", 20).
Q9. Why are default constructor parameters useful?
Answer: They allow objects to be created without explicitly supplying every parameter when a suitable default value exists.
Q10. What is a data class?
Answer: A data class is designed primarily to hold data and automatically provides methods such as toString(), equals(), hashCode(), and copy() for its primary-constructor properties.
Q11. What does this refer to in Kotlin?
Answer: The keyword this refers to the current object. It can also be used for constructor delegation in secondary constructors.
Q12. How are classes used in Android applications?
Answer: Classes represent data and application components, such as users, products, repositories, and business logic. Objects created from these classes are used throughout the application's workflow.
22. Quick Revision Checklist
- Understand the purpose of a class as a blueprint.
- Know how to create objects using constructor calls.
- Distinguish properties from member functions.
- Understand primary and secondary constructors.
- Use
val, var, default values, and named arguments correctly.
- Use
init blocks for initialization and validation.
- Understand constructor delegation with
this(...).
- Choose data classes for suitable data models.
- Apply encapsulation and avoid unnecessary mutable state.
- Practice building simple Kotlin models for Android applications.
23. Conclusion
Classes, objects, and constructors are essential building blocks of Kotlin and Android development. Classes organize properties and behavior, objects provide concrete instances, and constructors initialize those instances with the required values. Primary constructors, secondary constructors, default parameters, and init blocks provide flexible ways to create reliable objects.
By practicing these concepts with student, employee, product, and course models, you can build a strong foundation for developing maintainable Android applications. As you progress, apply the same principles to data models, application services, and other components of a well-structured Android project.
Additional Learning Resources