Scala case class extending Product with Serializable

匿名 (未验证) 提交于 2019-12-03 02:45:02

问题:

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

回答1:

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


回答2:

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 best matching resolution for the Array.

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

sealed trait Animal extends Product with Serializable 


回答3:

All case classes automatically extend Product and Serializable. It looks ugly ? yes. Basically ,Product can be viewed as heterogeneous collections. All Product classes viz. (Product1 , Product2 ...) extends Product which contains some common methods to use like productArity , productElement etc.

Like Case classes other types that extends Product are List,Tuple etc

From my scala worksheet,

  val product : Product = (10,"String",3)         //> product  : Product = (10,String,3)   product.productArity                            //> res0: Int = 3   product.productElement(0)                       //> res1: Any = 10   product.productElement(1)                       //> res2: Any = String   product.productElement(2)                       //> res3: Any = 3  case class ProductCase(age:Int,name:String,ISBN:Int)   ProductCase(23,"som",5465473).productArity      //> res4: Int = 3 

For details look here.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!