Scala Case Classes

Question Click to View Answer

What is the difference between a case class and a regular class. When should a case class be used? When should a case class be avoided.

Case classes provide instances with several built-in methods. Case classes are useful for objects that store data - for example, data transfer objects that are instantiated from a CSV file. Other classes should not inherit from case classes.

What does the following code print?

case class PersonData(name: String, age: Int)
val bob = PersonData("bob", 99)
val fred = bob.copy(name = "fred")
println(fred.age)

99 is printed.

The copy method is available for all instances of a case class. Instances of a regular class do not come built-in with a copy method. This code DOES NOT work:

class Person(name: String, age: Int)
val bob = new Person("bob", 99)
val fred = bob.copy(name = "fred")
println(fred.age)

What does the following code print?

case class PersonData(name: String, age: Int)
val bob1 = PersonData("bob", 99)
val bob2 = PersonData("bob", 99)
println(bob1 == bob2)

true is printed.

Case classes come with a built in equals method.

What does the following code print?

case class Dog(breed: String, age: Int)
val fido = Dog("lab", 4)
println(fido.toString)

Dog(lab,4) is printed.

Case classes come with a built-in toString method that prints the object as a string.

What does the following code print?

case class Cat(color: String)
val spanky = Cat("black")
println(spanky.color)

black is printed.

Case classes provide for easy access to the constructor arguments.

Case classes allow instances to be instantiated without using the new keyword (by leveraging Scala's apply method).

What does the following code print?

class Vampire(name: String) {
  def hobby = "sucking blood"
}

val d1 = new Vampire("dracula")
val d2 = new Vampire("dracula")

println(d1 == d2)

false is printed.

The behavior of == is different for regular classes and case classes.

Regular classes are not considered equal, even if they're both instances of the same class and have the same attributes. They're only considered equal if they point to the same object.

val count1 = new Vampire("Count Orlock")
val c2 = count1
count1 == c2 // true

What does the following code print?

class Vampire(name: String) {
  def hobby = "sucking blood"
}

val dracula = new Vampire("dracula")

println(dracula.name)

This code does not compile and throws an error.

The constructor arguments are not accessible by default with regular classes.

You need to define regular classes like this to make the constructor arguments accessible:

class Vampire(val name: String) {
  def hobby = "sucking blood"
}

What does the following code print?

class Bird(species: String)
val falcon = Bird("falcon")
print(falcon)

This code errors out.

Regular classes need to be instantiated with the new keyword.

The code needs to be updated as follows:

val falcon = new Bird("falcon")

Case classes do not need to be instantiated with the new keyword.

Explain the output of the following code:

class Chair(material: String)
val c = new Chair("wood")
println(c)

case class Bottle(material: String)
val b = Bottle("plastic")
println(b)

println(c) prints $line6.$read$$iw$Chair@4f281aaf.

println(b) prints Bottle(plastic).

The println function calls toString to print different types of objects. When println(44) is run, Scala will execute println(44.toString) under the hood.

Case classes define toString methods to pretty print objects, so they're easier for humans to read.

Regular classes do not automatically define a toString method, so they're not pretty printed.