Data Classes
Kotlin is a modern, concise language whose data classes hand you equals , hashCode , toString , copy , and destructuring for free — perfect for modelling plain data.
Learn Data Classes in our free Kotlin course — a beginner-friendly interactive lesson with worked examples, a practice exercise and a quick reference.
Part of the free Kotlin course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
By the end of this lesson you'll declare data classes and use content equality, copy() , and destructuring.
What You'll Learn in This Lesson
1️⃣ The data Keyword
Add data before class and the compiler generates toString() , equals() , hashCode() , copy() , and componentN() for you, all based on the constructor's properties.
Because equals and hashCode are consistent, two equal users count as one entry in a Set — exactly what you'd expect.
2️⃣ copy() and Destructuring
copy() creates a new instance with selected properties changed, leaving the original alone — the immutable way to "update" data. Destructuring unpacks properties into separate variables in one line.
Returning a data class and destructuring it is a clean way to return multiple related values from a function, as the minMax example shows.
Your turn. Replace the TODO , then run and compare.
Mini-Challenge: A Product Catalogue
Use copy() to apply a discount and destructuring to print a summary.
Common Errors (and the fix)
- "Data class must have at least one primary constructor parameter" — Add a property to the constructor; an empty data class isn't allowed.
- Body properties ignored by equals — Only constructor properties count in generated functions. Put data you want compared in the constructor.
- Mutating instead of copying — With val properties you can't reassign; use copy() to make a changed version.
- Using === to compare data — That checks identity, not content. Use == for value equality.
Pro Tips
- 💡 Prefer val properties in data classes for immutable, predictable models.
- 💡 Update state with copy(): it's the standard pattern in Compose and reducers.
- 💡 Destructure map entries and pairs too — for ((k, v) in map) uses the same machinery.
📋 Quick Reference — Data Classes
Concept
Kotlin Syntax
Declare
data class U(val n: String)
Content equality
a == b
Identity
a === b
Modified copy
u.copy(n = "Bob")
Destructure
val (n, a) = u
Frequently Asked Questions
🎉 Lesson Complete!
- ✅ data generates equals, hashCode, toString, copy, componentN
- ✅ == compares content; === compares identity
- ✅ copy() makes modified duplicates
- ✅ Destructuring unpacks properties in one line
- ✅ Only constructor properties feed the generated functions
- ✅ Next lesson: Inheritance & Interfaces
Practice quiz
Which functions does the 'data' keyword generate for a class?
- Only toString()
- equals(), hashCode(), toString(), copy(), and componentN()
- Just a constructor
- Only copy()
Answer: equals(), hashCode(), toString(), copy(), and componentN(). data generates equals, hashCode, toString, copy, and componentN based on the constructor properties.
What does == compare for two data class instances?
- Their structural content via equals()
- Their memory addresses
- Their class names only
- Always returns false
Answer: Their structural content via equals(). == is structural equality and calls equals(), comparing by content.
What does === check in Kotlin?
- Content equality
- Type compatibility
- Referential identity (same object in memory)
- Hash code equality only
Answer: Referential identity (same object in memory). === is referential equality: whether two references point to the same object.
What does copy() do on a data class?
- Mutates the original in place
- Deletes the original
- Converts it to a map
- Creates a new instance with selected properties changed
Answer: Creates a new instance with selected properties changed. copy() returns a new instance with chosen fields overridden, leaving the original untouched.
Which functions power destructuring of a data class?
- componentN() functions like component1()
- getValue() and setValue()
- iterator()
- compareTo()
Answer: componentN() functions like component1(). Destructuring uses componentN(); component1() returns the first property, and so on.
Which properties feed the generated equals/hashCode/toString/copy?
- All properties including body ones
- Only properties declared in the primary constructor
- Only the first property
- Only val properties in the body
Answer: Only properties declared in the primary constructor. Only primary-constructor properties are used; body properties are ignored by those functions.
What is a requirement for a data class?
- It must be abstract
- It must be open
- It must have no parameters
- It must have a primary constructor with at least one parameter
Answer: It must have a primary constructor with at least one parameter. A data class needs a primary constructor with at least one val/var parameter.
Two separately created data class objects with identical data are...
- == true and === true
- == true and === false
- == false and === true
- == false and === false
Answer: == true and === false. They have equal content (== true) but are different objects (=== false).
Which is NOT allowed for a data class?
- Being declared as abstract, open, sealed, or inner
- Having val properties
- Using copy()
- Being destructured
Answer: Being declared as abstract, open, sealed, or inner. Data classes cannot be abstract, open, sealed, or inner.
How many entries do two equal data class instances occupy in a Set?
- Two entries
- Zero entries
- One entry
- It throws an error
Answer: One entry. Because equals and hashCode are consistent, equal instances count as a single Set entry.
Continue this course
- Previous: Properties
- Next: Inheritance & Interfaces