-2

I have below code but when i remove case statement , object instance(Donut) cannot able to refer . I want to understand with simple example with class and case class statements , Please advise . Also i want to understand why '(' ')' is printed in my second print statement.

 case class Donut(name: String, tasteLevel: String)

   val favoriteDonut2: Donut = Donut("Glazed Donut", "Very Tasty")
   println(s"My favorite donut name = ${favoriteDonut2.name}, 
          tasteLevel =  ${favoriteDonut2.tasteLevel}")
   println( s"My fav donut name is = ${favoriteDonut2.name}",
            s"taste level is       = ${favoriteDonut2.tasteLevel}")

output:-
   My favorite donut name = Glazed Donut, tasteLevel = Very Tasty
   (My fav donut name is = Glazed Donut,taste level is     = Very Tasty)

1 Answers1

3

When you call Donut("Glazed Donut", "Very Tasty") you're really calling the apply method of the Donut object.
When you mark a class as a case class, scala will automatically generate a bunch of things for you, between them a companion object for your class with an apply method that takes all the arguments you define.
That's why if you define it as just a normal class, the line will fail - you can call new Donut("Glazed Donut", "Very Tasty") instead. Or you could create the apply method by hand.

class Donut(val name: String, val tasteLevel: String) // vals needed to make the fields public, case classes do this by default.
object Donut {
  /** Factory of Donuts */
  def apply(name: String, tasteLevel: String): Donut = new Donut(name, tasteLevel)
}

Note

Case Classes provide another bunch of useful functionalities appart of a simple constructor, like: pretty toString implementation, good hashCode implementation, "by value" comparison, simple "copying", extractors for pattern matching, etc - that remove "boilerplate" from the code.
Thus if you need a couple of these features and the class is not intended to be mutated, prefer a case class than implementing everything by yourself.

" Also i want to understand why '(' ')' is printed in my second print statement."

Scala's print function, only receives one argument. Thus, what happens when you write print(a, b) is that you call print with the tuple (a, b) - (which is the same as calling print((a, b))).

  • Hi so correct me if my understanding is wrong. when i dont use new keyword to create an instance of an object then it will be by default we need to use 'case' before class definition ? – Balaji Krishnamoorthy Nov 15 '18 at 16:22
  • @BalajiKrishnamoorthy not necessarily, This `new C(a, b)` means call a **method**, _(called the constructor)_, from a **class** `C` passing the **arguments** `a` & `b`. Whereas, this `foo(a, b)` means call the `apply` **method** from foo passing the **arguments** `a` & `b`. If foo is an instance of a **class** `C` such class must define that method, but foo could also be an [scala **object**](https://docs.scala-lang.org/tour/singleton-objects.html), is the object itself the one that must define the **method** - usually the **object** will be a **companion object** from some **class**... – Luis Miguel Mejía Suárez Nov 15 '18 at 18:57
  • ... in those cases, usually the `apply` **method** is seen as a factory of instances of the **class**. Making a **class** a **case class** will guarantee the **companion object** and the `apply` **method**, because the Scala compiler itself will generate them. But, nothing stops you from doing the same by hand - I will update the answer to provide an example. – Luis Miguel Mejía Suárez Nov 15 '18 at 19:01