Kotlin Data Classes in Depth
Beyond the generated equals and toString, a data class also generates component functions and a copy function.
Reading parts with component functions
component1() returns the first property in constructor order. component2() returns the second.
data class Point(val x: Int, val y: Int)
fun main() {
val pt = Point(2, 3)
println(pt.component1())
println(pt.component2())
}copy changes one field
The copy keeps the title and takes a new pages value. The original prints unchanged on the first line.
data class Book(val title: String, val pages: Int)
fun main() {
val book = Book("Dune", 412)
val shorter = book.copy(pages = 300)
println(book)
println(shorter)
}A copy shares its nested object
The copy gets a new name but keeps the same Address object. The printed address field is the field of that shared object.
data class Address(val city: String)
data class Person(val name: String, val address: Address)
fun main() {
val ana = Person("Ana", Address("Porto"))
val copy = ana.copy(name = "Ana Maria")
println(copy.name)
println(copy.address)
println(copy.address.city)
}Pair and Triple are data classes
Pair holds two values and Triple holds three. Both expose first, second, and the component functions.
fun main() {
val pair = Pair("Ana", 90)
println(pair.first)
println(pair.second)
val triple = Triple("Bo", 75, true)
println(triple)
println(triple.component3())
}An empty data class fails
Empty declares no primary constructor parameter at all. The compiler rejects the data class on its first line.
data class Empty()
fun main() {
println(Empty())
}Example
data class Size(val width: Int, val height: Int)
data class Frame(val label: String, val size: Size)
fun main() {
val frame = Frame("photo", Size(10, 8))
val bigger = frame.copy(size = Size(12, 8))
println(frame.size.component1())
println(bigger.size.component2())
println(bigger)
}Key points
- Each primary constructor property of a data class gets a component function.
- component1() reads the first property, and component2() reads the second.
- copy() returns a new object with the named fields changed.
- copy() leaves the original object untouched.
- A copy shares nested objects with the original, because copy() does not clone them.
- Pair and Triple are ready-made data classes from the standard library.
In this example, the copy swaps the whole Size object for a wider one. component1() reads the width of the original size, and component2() reads the height of the copied size. The last line prints the full copied frame.
Note
a data class must declare at least one primary constructor parameter.
Try it Yourself
Edit the code, then press Run.
Running is simulated ยท Kotlin Playground
Exercise
For data class Point(val x: Int, val y: Int) and val pt = Point(2, 3), what does pt.component2() return?