When to use case class or regular class

Scala

Scala Problem Overview


I have some misunderstanding in what cases I should use case class or regular class following by best practices. I have already read about differences of both classes but cannot imagine myself real-life examples where is reccommended to use case or regular class.

Could anybody show me real examples with explanation why it's reccommended to do so and not otherwise?

Scala Solutions


Solution 1 - Scala

If you are going to write purely functional code with immutable objects, you should better try avoid using regular classes. The main idea of the functional paradigm is the separation of data structures and operations on them. Case Classes are a representation of a data structure with the necessary methods. Functions on the data should be described in different software entities (e.g., traits, objects).

Regular classes, on the contrary, link data and operations to provide the mutability. This approach is closer to the object-oriented paradigm.


As a result, do not use Case Classes if:

  1. Your class carries mutable state.
  2. Your class includes some logic.
  3. Your class is not a data representation and you do not require structural equality.

However, in these cases, you should really think about the style of your code because it probably is not functional enough.

Solution 2 - Scala

Case Classes are normal classes with syntactic sugar. So there is no real big difference, you can do everything with a case class you can do with a class and vice versa.

Case classes just save you a lot of boiler plate code to write.

Perfect fit, as the name suggests, is the use of case classes in pattern matching with case.

case class MyCase(name: String, age: Int)

data : List[MyCase] = ...

data foreach { 
    case MyCase(_, age) if age > 21 => println("old enough")
    case MyCase("fred", _ ) => println("Got you")
    case _ => ...
}

Solution 3 - Scala

  1. When your class carries mutable state, do not use case classes.
  2. When you want structural equality, do use a case class, as it gives you proper hashCode and equals. For example, you want to be able to use them as keys into a Set or Map

Here is another more personal preference:

  • When you simply want the automatic getters, and you put instances in a Set or Map, but you only ever have one instance and do not require structural equality, prefer class Foo(val i: Int) over case class Foo(i: Int), because you don't have possibly more expensive equality checks.

If 1. and 2. collide, you can implement specific case class features by hand. For example, provide a companion apply method or a pattern-matching extractor for a mutable non-case class.

Solution 4 - Scala

case classes are datacentric.

We get following advantages by using case class over regular classes.

(1) Value equivalence : It means that two case instances can be compared against values inside them.

scala> case class Time(hours: Int = 0, mins: Int = 0)
defined class Time

scala> val time1 = Time(12, 13)
time1: Time = Time(12,13)

scala> val time2 = Time(11, 12)
time2: Time = Time(11,12)

scala> time1 == time2
res6: Boolean = false

scala> val time3 = Time(10, 11)
time3: Time = Time(10,11)

scala> time1 == time2
res7: Boolean = false

But other comparison operators(>, >= <, etc) are not defined.

(2) Immutable Fields: Thread-safe

(3) Automatic field creation: hours and minutes are immutable fields automatically created by Scala.

scala> time1.hours
res9: Int = 12

case classes are also used in parsing spark DataFrame rows and advantage is that columns of DataFrame can be accessed by field name of case class.

Solution 5 - Scala

A case class gives you "free" (i.e., you don't have to write) implementations of equals, hashcode and toString, as well as apply and unapply in the companion object. Basically, you can think of a case class as a named tuple, whose fields are named as well.

For anything else, you're probably better off using a normal class.

Solution 6 - Scala

Normal classes are classes as classes in Java. It can contain both state and functionality.
Case classes are like data POJO in Java. classes that hold state, which can be used by functions (usually in other classes).

When you are implementing data POJO in Java you should set the variable it hold, add getter and setter for them, implement hashcode and equals, and probably implement toString.
Usually it's not that bad since after defining the variables, the IDE can generate all for you, but if you change/add variables then you should remember to update all the methods.
in case classes you define the variables (or better values) and the compiler generate all the methods for you. So you gain both, no boilerplate and updated functionality.
For case classes the compiler also generate more functionality, that you don't and can't have in Java, the copy function and apply/unapply in the companion object.

Solution 7 - Scala

Case class works like Java's record class and Lombok library. You can save lots of boilerplate code like getters and setters.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionViktor M.View Question on Stackoverflow
Solution 1 - ScalahellraiserView Answer on Stackoverflow
Solution 2 - ScalaAndreas NeumannView Answer on Stackoverflow
Solution 3 - Scala0__View Answer on Stackoverflow
Solution 4 - Scalaanshu kumarView Answer on Stackoverflow
Solution 5 - ScalaGalView Answer on Stackoverflow
Solution 6 - ScalaroterlView Answer on Stackoverflow
Solution 7 - ScalaBrian SuView Answer on Stackoverflow