Case Classes

    Case classes are just like regular classes with a few key differences, which are below:

    1. A case class can be created using the keyword case class instead of simply class.

    2. Case classes promote immutability. That's why the class parameters, if not mentioned, will be public vals by default.

    case class Letter(sender: String, recipient: String, body: String)
    val message1 = Letter("Geet", "Prerna", "Lets meet in the coming week at our usual location")
    println(message1.sender)  // It will print Geet
    message1.sender = "Pari"  // Will give error "reassignment to val"

    Note: It is also possible to use vars in case classes, but this is discouraged

    3. Copy method for creating new instances easily.

    message1.copy(recipient = "Nikita") 
    // This is going to create a new instance by just updating recipient value
    4. Provides easy Pattern matching
    case class Person(firstName: String, lastName: String)
    case class Pet(name: String, animal: String)
    val listOfPets = List(Pet("Ginger", "Dog"),
     Pet("boo", "Cat"),
     Pet("Tommy", "Dog"),
     Pet("Bow", "Dog")) {
     case Pet(name, "Dog") => s"$name is a Dog"
     case _ => "The pet is not a Dog :)"

    5. Instances of case classes are compared by structure and not by reference