Case classes in Scala are a special kind of classes that come with some built-in features, making them particularly useful for modeling immutable data structures and for pattern matching. A case class is defined using the ‘case class‘ keyword, and its constructor parameters are automatically public ‘val‘ fields. It also has some default implementations of critical methods like ‘equals‘, ‘hashCode‘, and ‘toString‘, and automatically generates a companion object with ‘apply‘ and ‘unapply‘ methods to facilitate object creation and pattern matching.
Here’s an example of a case class modeling a 2D point:
case class Point(x: Double, y: Double)
Here are some notable features of case classes:
1. **Immutable data:** By default, constructor parameters of a case class are immutable ‘val‘s, promoting the use of immutable data structures.
val point = Point(1.0, 2.0)
// It's already a val, no need for 'new'
// point.x = 3.0 // Error: Reassignment to val
2. **Equals and HashCode:** Case classes have ‘equals‘ and ‘hashCode‘ methods automatically implemented for value comparison based on their contents.
val point1 = Point(1.0, 2.0)
val point2 = Point(1.0, 2.0)
val point3 = Point(3.0, 4.0)
println(point1 == point2) // true
println(point1 == point3) // false
3. **To string:** ‘toString‘ method is automatically implemented for a readable print representation.
println(point1) // Point(1.0, 2.0)
4. **Apply:** A companion object with an ‘apply‘ method is automatically generated, allowing you to create instances without the ‘new‘ keyword.
val point = Point(1.0, 2.0) // automatically calls the apply method
5. **Unapply:** The companion object also has an ‘unapply‘ method to support pattern matching.
point match {
case Point(x, y) => println(s"X: $x, Y: $y") // X: 1.0, Y: 2.0
case _ => println("Unknown")
}
6. **copy:** A ‘copy‘ method is generated to create a new instance with selective updates, making it easier to work with immutable data.
val point = Point(1.0, 2.0)
val newPoint = point.copy(y = 3.0) // Point(1.0, 3.0)
In summary, case classes in Scala not only promote immutability but also offer several convenient methods for comparison, pattern matching, and easier instantiation.