๐ŸŽ“ A1Learner
๐Ÿ”
0 of 37 lessons completed

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?