Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala case class extending Product with Serializable

I am learning scala and tried following form Scala Cookbook:

trait Animal
trait FurryAnimal extends Animal
case class Dog(name:String) extends Animal
case class Cat(name:String) extends Animal

Now when I did following as :

val x = Array(Dog("Fido"),Cat("Felix"))

it show result as :

x:Array[Product with Serializable with Animal] = Array(Dog(Fido),Cat(Felix))

Although I know that a case class is mixed in with Product trait

What I am not getting is : Product with Serializable with Animal

As per my understanding Product has something to do with Pattern matching

I did google it but didn't get anything.Please Help to get me the concept in detail.

Thanks

like image 830
optional Avatar asked Apr 10 '16 04:04

optional


People also ask

Is case class Serializable in Scala?

Case objects are similar to Scala objects with a few critical differences. The main differences are that case objects are serializable and have a default hashCode implementation as well as a toString implementation. Case objects are useful for enumerations and creating containers for messages.

Can Scala case class be extended?

Case Class can NOT extend another Case class. However, they have removed this feature in recent Scala Versions. So a Case Class cannot extend another Case class. NOTE:- In Scala Language, case-to-case inheritance is prohibited.

What is product with serializable?

Product serialization is the process of assigning a unique identity to each saleable product item. This identity can be assigned by affixing a unique code on each product item, usually in the form of QR code or NFC or RFID, etc.

What is serializable in Scala?

Serializing an object means taking the data stored in an object and converting it to bytes (or a string). Suppose you want to write the data in an object to a JSON file. JSON files store strings. JSON has no understanding about the JVM or Scala objects.


2 Answers

This is an expected behavior because of how case class works. case class automatically extends two traits, namely Product and Serializable.

Product trait is extended as case class is an algebraic data type with product type.

Serializable trait is extended so that case class can be treated as a pure data - i.e capable of being serialized.

Unlike case class Dog and Cat, your trait Animal does not extend Product or Serializable. Hence the type signature you see.

When you declare something like Array(Dog(""), Cat("")), scalac needs to infer single top type that can represent all the elements of given array.

That's why the inferred type is Product with Serializable with Animal as Animal did not extend Product nor Serializable while the case class did implicitly.

To work around this inference, you can either make type explicit by Animal or make Animal extend Product and Serializable.

trait Animal extends Product with Serializable

case class Dog(name: String) extends Animal
case class Cat(name: String) extends Animal

Array(Dog(""), Cat("")) // Array[Animal] = Array(Dog(), Cat())
like image 164
Daniel Shin Avatar answered Oct 17 '22 16:10

Daniel Shin


All case classes in Scala posses a few properties:

  1. They will automatically extend the Product trait and a default implementation will be provided for them, as they can be viewed as a Cartesian Product of N records.
  2. They will extend Serializable as they are serializable out of the box (as a design choice).
  3. They will have an implementation of hashCode and equals provided by the compiler, which aids with pattern matching
  4. They will provide apply and unapply methods, for composition and decomposition of the type.

Case classes are also Scala's way of expressing an Algebraic Data Type, more specifically a Product Type. Tuples are also a product type, and as so they also extend the Product trait.

When you use two case classes with a common trait, the scala's compiler will use it's type inference algorithm to attempt to find the least upper bound (LUB) for the T type of the Array. Since both case classes extend Product and Serializable through the compiler, and the trait does not, it will during the search and apply it to the final calculated type.

If you want to avoid seeing that, you can have your trait explicitly extend those traits:

sealed trait Animal extends Product with Serializable

More on this topic can be found here

like image 15
Yuval Itzchakov Avatar answered Oct 17 '22 17:10

Yuval Itzchakov