Kotlin Data Classes
Classes designed primarily to hold data with automatic functionality
📊 What are Data Classes?
Data classes in Kotlin are special classes designed to hold data. They automatically generate useful methods like equals(), hashCode(), toString(), and copy(), reducing boilerplate code while providing powerful functionality for data manipulation and comparison.
// Simple data class example
data class Person(val name: String, val age: Int)
Data Class Features
Auto-generated Methods
equals(), hashCode(), toString()
data class User(val name: String)
// Automatically gets comparison methods
Copy Function
Create copies with modifications
val user2 = user1.copy(name = "New Name")
Destructuring
Extract properties easily
val (name, age) = person
Primary Constructor
At least one parameter required
data class Point(val x: Int, val y: Int)
🔹 Basic Data Class
Here's how to create and use a simple data class:
data class Student(
val name: String,
val age: Int,
val grade: String
)
fun main() {
val student1 = Student("Alice", 20, "A")
val student2 = Student("Alice", 20, "A")
val student3 = Student("Bob", 21, "B")
// Automatic toString()
println(student1)
// Automatic equals()
println("student1 == student2: ${student1 == student2}")
println("student1 == student3: ${student1 == student3}")
// Automatic hashCode()
println("student1 hashCode: ${student1.hashCode()}")
println("student2 hashCode: ${student2.hashCode()}")
}
Output:
Student(name=Alice, age=20, grade=A)
student1 == student2: true
student1 == student3: false
student1 hashCode: -1706434656
student2 hashCode: -1706434656
🔹 Copy Function
Create modified copies of data class instances:
data class Product(
val name: String,
val price: Double,
val category: String,
val inStock: Boolean = true
)
fun main() {
val laptop = Product("Gaming Laptop", 1299.99, "Electronics")
println("Original: $laptop")
// Copy with price change
val discountedLaptop = laptop.copy(price = 999.99)
println("Discounted: $discountedLaptop")
// Copy with multiple changes
val outOfStockLaptop = laptop.copy(
price = 1199.99,
inStock = false
)
println("Out of stock: $outOfStockLaptop")
// Original remains unchanged
println("Original unchanged: $laptop")
}
Output:
Original: Product(name=Gaming Laptop, price=1299.99, category=Electronics, inStock=true)
Discounted: Product(name=Gaming Laptop, price=999.99, category=Electronics, inStock=true)
Out of stock: Product(name=Gaming Laptop, price=1199.99, category=Electronics, inStock=false)
Original unchanged: Product(name=Gaming Laptop, price=1299.99, category=Electronics, inStock=true)
🔹 Destructuring Declarations
Extract properties from data classes easily:
data class Coordinate(val x: Int, val y: Int, val z: Int)
data class Person(val firstName: String, val lastName: String, val age: Int)
fun main() {
val point = Coordinate(10, 20, 30)
// Destructuring assignment
val (x, y, z) = point
println("Point coordinates: x=$x, y=$y, z=$z")
// Partial destructuring
val (xOnly, yOnly) = point
println("Only x and y: x=$xOnly, y=$yOnly")
// Using underscore to skip values
val (_, _, zOnly) = point
println("Only z: z=$zOnly")
// Destructuring in function parameters
fun printPersonInfo(person: Person) {
val (first, last, age) = person
println("Name: $first $last, Age: $age")
}
val person = Person("John", "Doe", 25)
printPersonInfo(person)
}
Output:
Point coordinates: x=10, y=20, z=30
Only x and y: x=10, y=20
Only z: z=30
Name: John Doe, Age: 25
🔹 Data Classes in Collections
Data classes work great with collections due to proper equals() and hashCode():
data class Book(val title: String, val author: String, val year: Int)
fun main() {
val books = listOf(
Book("1984", "George Orwell", 1949),
Book("To Kill a Mockingbird", "Harper Lee", 1960),
Book("1984", "George Orwell", 1949), // Duplicate
Book("The Great Gatsby", "F. Scott Fitzgerald", 1925)
)
println("All books:")
books.forEach { println(" $it") }
// Remove duplicates using Set
val uniqueBooks = books.toSet()
println("\nUnique books:")
uniqueBooks.forEach { println(" $it") }
// Find books by author
val orwellBooks = books.filter { it.author == "George Orwell" }
println("\nBooks by George Orwell:")
orwellBooks.forEach { println(" $it") }
// Group by decade
val booksByDecade = books.groupBy { (it.year / 10) * 10 }
println("\nBooks by decade:")
booksByDecade.forEach { (decade, bookList) ->
println(" ${decade}s: ${bookList.size} books")
}
}
Output:
All books:
Book(title=1984, author=George Orwell, year=1949)
Book(title=To Kill a Mockingbird, author=Harper Lee, year=1960)
Book(title=1984, author=George Orwell, year=1949)
Book(title=The Great Gatsby, author=F. Scott Fitzgerald, year=1925)
Unique books:
Book(title=1984, author=George Orwell, year=1949)
Book(title=To Kill a Mockingbird, author=Harper Lee, year=1960)
Book(title=The Great Gatsby, author=F. Scott Fitzgerald, year=1925)
🔹 Data Class Requirements
Understanding data class constraints and best practices:
// ✅ Valid data class
data class ValidUser(val name: String, val email: String)
// ✅ Data class with default values
data class UserProfile(
val username: String,
val isActive: Boolean = true,
val joinDate: String = "2024-01-01"
)
// ✅ Data class with additional properties
data class Employee(val id: Int, val name: String) {
var department: String = "Unassigned" // Not part of equals/hashCode
fun getDisplayName() = "Employee #$id: $name"
}
fun main() {
val user1 = ValidUser("Alice", "[email protected]")
val user2 = ValidUser("Alice", "[email protected]")
println("Users equal: ${user1 == user2}")
val profile = UserProfile("john_doe")
println("Profile: $profile")
val emp1 = Employee(1, "John")
val emp2 = Employee(1, "John")
emp1.department = "IT"
emp2.department = "HR"
// Still equal because department is not in primary constructor
println("Employees equal: ${emp1 == emp2}")
println("Employee 1: ${emp1.getDisplayName()}, Dept: ${emp1.department}")
println("Employee 2: ${emp2.getDisplayName()}, Dept: ${emp2.department}")
}
Output:
Users equal: true
Profile: UserProfile(username=john_doe, isActive=true, joinDate=2024-01-01)
Employees equal: true
Employee 1: Employee #1: John, Dept: IT
Employee 2: Employee #1: John, Dept: HR