spark - scala pattern matching case class
Caso de Scala extendiendo Producto con Serializable (3)
Estoy aprendiendo scala y probé el siguiente libro de cocina de Scala:
trait Animal
trait FurryAnimal extends Animal
case class Dog(name:String) extends Animal
case class Cat(name:String) extends Animal
Ahora cuando lo hice siguiendo como:
val x = Array(Dog("Fido"),Cat("Felix"))
se muestra el resultado como:
x:Array[Product with Serializable with Animal] = Array(Dog(Fido),Cat(Felix))
Aunque sé que una clase de caso se mezcla con el rasgo del producto
Lo que no estoy obteniendo es: Product with Serializable with Animal
Según mi entendimiento, el producto tiene algo que ver con la coincidencia de patrones
Lo busqué en Google pero no obtuve nada. Por favor, ayuda para obtener el concepto en detalle.
Gracias
Este es un comportamiento esperado debido a cómo funciona la case class
. case class
extends
automáticamente dos rasgos, a saber, Product
y Serializable
.
Product
rasgo del Product
se extiende ya case class
es un tipo de datos algebraico con tipo de producto .
Serializable
rasgo Serializable
se extiende para que la case class
se pueda tratar como datos puros, es decir, se pueda serializar.
A diferencia de la case class
Dog
y Cat
, su rasgo Animal
no extiende el Product
o Serializable
. De ahí el tipo de firma que ves.
Cuando declara algo como Array(Dog(""), Cat(""))
, scalac necesita inferir un tipo superior único que pueda representar todos los elementos de un array dado.
Es por eso que el tipo inferido es Product with Serializable with Animal
como Animal
no extendió el Product
ni Serializable
mientras que la case class
hizo implícitamente.
Para evitar esta inferencia, puede hacer que el tipo sea explícito por Animal
o hacer que Animal
extienda el Product
y 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())
Todas las clases de casos en Scala poseen algunas propiedades:
- Extenderán automáticamente el rasgo del
Product
y se les proporcionará una implementación predeterminada, ya que pueden verse como un producto cartesiano de N registros . - Se extenderán como
Serializable
ya que se pueden serializar fuera de la caja (como opción de diseño). - Tendrán una implementación de
hashCode
yequals
proporcionada por el compilador, lo que ayuda con la coincidencia de patrones. - Proporcionarán métodos de
apply
y nounapply
, para la composición y descomposición del tipo.
Las clases de casos también son la forma de Scala de expresar un tipo de datos algebraico , más específicamente un tipo de producto . Las tuplas también son un tipo de producto , y como tal también extienden el rasgo del Product
.
Cuando usa dos clases de casos con un rasgo común, el compilador de Scala usará su algoritmo de inferencia de tipo para tratar de encontrar la mejor resolución de coincidencia para el Array
.
Si desea evitar ver este detalle de implementación, puede hacer que su rasgo amplíe explícitamente esos rasgos:
sealed trait Animal extends Product with Serializable
Todas las clases de casos extienden automáticamente Product
y Serializable
. Se ve feo? sí. Básicamente, el Product
puede verse como colecciones heterogéneas. Todas las clases de productos a saber. (Producto1, Producto2 ...) amplía el Product
que contiene algunos métodos comunes para usar como productoAridad, productElement
, productElement
, etc.
Al igual que las clases de casos, otros tipos que amplían el Product
son List
, Tuple
, etc.
De mi hoja de trabajo de Scala,
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
Para más detalles mira aquí .