Scala案例类使用Serializable扩展Product

opt*_*nal 21 types scala traits case-class

我正在学习scala并尝试了以下形式Scala Cookbook:

trait Animal
trait FurryAnimal extends Animal
case class Dog(name:String) extends Animal
case class Cat(name:String) extends Animal
Run Code Online (Sandbox Code Playgroud)

现在,当我做到以下时:

val x = Array(Dog("Fido"),Cat("Felix"))
Run Code Online (Sandbox Code Playgroud)

它显示结果为:

x:Array[Product with Serializable with Animal] = Array(Dog(Fido),Cat(Felix))
Run Code Online (Sandbox Code Playgroud)

虽然我知道案例类与Product trait混在一起

我没有得到的是: Product with Serializable with Animal

据我所知,产品与模式匹配有关

我确实谷歌它,但没有得到任何东西.请帮助我详细了解这个概念.

谢谢

Dan*_*hin 45

这是一种预期的行为,因为它的case class工作原理.case class自动extends两个特征,即ProductSerializable.

Product特征扩展为具有产品类型case class代数数据类型.

Serializable特征被扩展,因此case class可以被视为纯数据 - 即能够被序列化.

case class Dog和不同Cat,你的特质Animal不会延伸ProductSerializable.因此,您看到的类型签名.

当你声明类似的东西时Array(Dog(""), Cat("")),scalac需要推断出可以代表给定数组的所有元素的单顶类型.

这就是为什么推断类型Product with Serializable with AnimalAnimal没有扩大Product,也没有Serializable,而case class隐含一样.

要解决这一推论,你可以做类型的露骨Animal或进行Animal扩展ProductSerializable.

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())
Run Code Online (Sandbox Code Playgroud)

  • 感谢您的解释和维基链接,这些链接让我清楚了解数学模型. (2认同)

Yuv*_*kov 13

Scala中的所有案例类都具有一些属性:

  1. 它们将自动扩展Product特征,并为它们提供默认实现,因为它们可被视为N个记录的笛卡尔积.
  2. 它们将扩展,Serializable因为它们可以开箱即用(作为设计选择).
  3. 它们将具有编译器的实现hashCodeequals提供,这有助于模式匹配
  4. 他们将提供applyunapply方法,用于组合和分解类型.

案例类也是Scala表达代数数据类型的方式,更具体地说是产品类型.元组也是一种产品类型,因此它们也扩展了Product特性.

当您使用具有共同特征的两个案例类时,scala的编译器将使用它的类型推断算法来尝试找到最佳匹配分辨率Array.

如果您想避免看到此实现细节,可以让您的特征显式扩展这些特征:

sealed trait Animal extends Product with Serializable
Run Code Online (Sandbox Code Playgroud)