logo
Scala - Interview Questions and Answers
What are case classes and how are they different from regular classes in Scala?
In Scala, case classes are a special type of classes that are primarily used to hold immutable data. They provide several additional features and conveniences compared to regular classes. Here are the key differences between case classes and regular classes:

1. Boilerplate Code : Case classes automatically generate boilerplate code, including equality, hashCode, and toString methods, which makes them convenient for modeling immutable data. This saves you from writing these common methods manually.

2. Immutability : Case classes are immutable by default. The parameters of a case class are automatically declared as `val`, making the instances immutable. This ensures that the data contained in a case class cannot be modified after creation.

3. Pattern Matching : Case classes work seamlessly with pattern matching. They automatically generate an extractor pattern, which allows you to conveniently destructure case class instances and extract their values for pattern matching.

4. Copying : Case classes provide a built-in `copy` method that allows you to create a copy of an instance with some or all of its fields modified. This is useful when you need to create a new instance that is similar to an existing instance but with some changes.

5. Companion Object : A case class automatically generates a companion object with useful methods, such as `apply`, `unapply`, and `toString`. The `apply` method allows you to create instances of the case class without using the `new` keyword.

6. Structural Equality : Case classes define structural equality by default. Two instances of the same case class are considered equal if their fields have the same values.

7. Default Implementation : Case classes provide a default implementation of the `toString` method, which prints a string representation of the case class instance, including the class name and its fields.
Here's an example that demonstrates the usage of a case class :
case class Person(name: String, age: Int)

val person1 = Person("John", 30)
val person2 = Person("John", 30)

println(person1 == person2) // Output: true (structural equality)
println(person1.toString) // Output: Person(John,30)

val modifiedPerson = person1.copy(age = 35)
println(modifiedPerson) // Output: Person(John,35)​

In this example, the `Person` case class is defined with `name` and `age` parameters. The case class automatically generates methods such as `equals`, `hashCode`, `toString`, and `copy`. We create two instances of the `Person` case class with the same values for `name` and `age`, and they are considered equal due to structural equality.

We can use the `copy` method to create a modified copy of a case class instance. In this example, we modify the `age` field of `person1` to 35, resulting in a new instance with the same `name` but a different `age`.

Case classes are widely used in Scala for representing immutable data structures, modeling domain entities, and facilitating pattern matching. Their concise syntax, automatic code generation, and immutability make them a powerful construct for functional programming and data modeling.