Kotlin by Example: Data Classes
Reducing boilerplate for data holders with this code example showing data class declaration, automatically generated equals/hashCode/toString methods, copy function for immutable updates, and destructuring declarations.
Code
// Define a data class
data class User(val name: String, val age: Int)
fun main() {
val user1 = User("Alice", 25)
val user2 = User("Alice", 25)
val user3 = User("Bob", 30)
// 1. toString() is generated automatically
println(user1) // Output: User(name=Alice, age=25)
// 2. equals() checks for structural equality (content)
println(user1 == user2) // true
// 3. copy() allows cloning with modification
val olderAlice = user1.copy(age = 26)
println(olderAlice) // User(name=Alice, age=26)
// 4. Destructuring declarations
val (name, age) = user1
println("$name is $age")
}Explanation
Data classes in Kotlin are designed primarily for holding data and are marked with the data keyword. The compiler automatically generates several utility methods based on properties declared in the primary constructor, eliminating boilerplate code required in languages like Java. These classes must have at least one parameter in their primary constructor, and all primary constructor parameters must be marked as val or var.
Automatically generated methods for data classes include:
equals()method compares structural equality based on property valueshashCode()method generates hash codes consistent with equals implementationtoString()method returns string representation in format "ClassName(property1=value1, property2=value2)"copy()method creates shallow copy with ability to change specific propertiescomponentN()functions enable destructuring declarations for unpacking objects
The copy() method is particularly valuable for working with immutable data structures. Since data classes often use val properties, direct modification is impossible. The copy() method creates a new instance copying all properties from the original, with named parameters allowing selective property changes. Destructuring declarations use the generated componentN() functions to unpack objects into individual variables in declaration order.
Code Breakdown
data class User(...) triggers automatic generation of utility methods.user1 == user2 uses generated equals, compares property values not references.user1.copy(age = 26) creates new instance with modified age property.val (name, age) = user1 destructuring uses componentN functions.
