Scala case class extending Product with Serializable

optional picture optional · Apr 10, 2016 · Viewed 23.9k times · Source

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

Answer

Daniel Shin picture Daniel Shin · Apr 10, 2016

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())