Case Class
Case classes in Scala are a special type of class that is optimized for use in pattern matching and immutability by default. They come with several boilerplate features out of the box, such as sensible toString
, equals
, and hashCode
implementations, as well as the ability to be deconstructed in pattern matching. Case classes are immensely useful for defining simple data-holding objects, making them a staple in functional programming and domain modeling in Scala.
Basic Case Class
Defining a case class is straightforward:
case class Person(name: String, age: Int)
This declaration automatically provides:
- Immutable fields:
name
andage
are public val fields by default. - Sensible
toString
,equals
, andhashCode
methods based on the class's fields. - An
apply
method, allowing you to instantiate the class without thenew
keyword. - An
unapply
method, making it eligible for use in pattern matching.
Instantiating a Case Class
You can instantiate a case class without the new
keyword, thanks to the automatically provided apply
method:
val alice = Person("Alice", 30)
Copying
Case classes come with a copy
method, which is useful for creating a new instance of the class with some changed attributes while keeping the rest unchanged:
val bob = alice.copy(name = "Bob")
This creates a new Person
instance with the name "Bob" and the same age as alice
.
Pattern Matching
Case classes shine when used in pattern matching, thanks to their unapply
method:
alice match
case Person(name, age) => println(s"Name: $name, Age: $age")
case _ => println("Unknown person")
This pattern matching checks if alice
is a Person
instance and then extracts and prints the name
and age
.
Companion Objects
A companion object for the case class is automatically generated, containing the apply
and unapply
methods among others. This means you can add additional static utility methods or values in the companion object if needed:
object Person:
def isAdult(person: Person): Boolean = person.age >= 18
val adultCheck = Person.isAdult(alice) // true
Use Cases
Case classes are ideal for:
- Domain models: Representing data entities in your domain.
- Data transfer objects (DTOs): Encapsulating data sent between processes or systems.
- Immutable data structures: Building complex data structures that benefit from immutability.