Scala by Example: Case Classes
Modeling immutable data structures with this sample code demonstrating case class auto-generated methods, instantiation without new keyword, structural equality comparison, copy method for creating modified instances, built-in toString implementation, and seamless pattern matching support.
Code
// Define a case class
case class Point(x: Int, y: Int)
// Instantiation (no 'new' needed)
val p1 = Point(1, 2)
val p2 = Point(1, 2)
val p3 = Point(3, 4)
// Equality check (by value, not reference)
println(p1 == p2) // true
// Copying with modification
val p4 = p1.copy(y = 5) // Point(1, 5)
// Built-in toString
println(p4) // "Point(1,5)"
// Pattern matching support
p1 match {
case Point(0, 0) => println("Origin")
case Point(x, y) => println(s"At $x, $y")
}Explanation
Case classes are specialized classes optimized for modeling immutable data, and they're one of Scala's most beloved features. When you define a class as a case class, the compiler automatically generates substantial boilerplate code including:
- An
applymethod in the companion object for instantiation withoutnew - An
unapplymethod enabling pattern matching and deconstruction equalsandhashCodemethods implementing structural equality- A
toStringmethod providing meaningful string representation - A
copymethod for creating modified copies while maintaining immutability
Structural equality is one of the most important features of case classes. Two case class instances are considered equal if all their fields are equal, unlike regular classes which compare object references by default. This makes case classes ideal for value objects, data transfer objects, and any scenario where you care about the data content rather than object identity. The generated hashCode method ensures case class instances work correctly in hash-based collections like HashMap and HashSet.
The copy method allows you to create a new instance based on an existing one with some fields modified, which is essential for working with immutable data structures. Instead of mutating an object, you create a modified copy. Case classes are designed to work seamlessly with pattern matching, allowing you to deconstruct them easily and extract their fields in match expressions, making them perfect for algebraic data types and domain modeling.
Code Breakdown
case class Point(...) automatically generates val fields and utility methods.p1 == p2 compares by value (structural equality), not reference.p1.copy(y = 5) creates new Point keeping x from p1 but changing y.case Point(x, y) deconstructs case class extracting fields for pattern matching.
