Scala класс корпуса, расширяющий продукт с помощью Serializable
Я изучаю scala и пробовал следующую форму scala Cookbook:
trait Animal
trait FurryAnimal extends Animal
case class Dog(name:String) extends Animal
case class Cat(name:String) extends Animal
Теперь, когда я сделал следующее:
val x = Array(Dog("Fido"),Cat("Felix"))
он показывает результат как:
x:Array[Product with Serializable with Animal] = Array(Dog(Fido),Cat(Felix))
Хотя я знаю, что класс case смешивается с характеристикой Product
То, что я не получаю, это: Product with Serializable with Animal
В соответствии с моим пониманием Продукт имеет отношение к сопоставлению с образцом
Я сделал google, но ничего не получил. Пожалуйста, помогите мне детально описать концепцию.
Спасибо
Ответы
Ответ 1
Это ожидаемое поведение из-за того, как работает case class
. case class
автоматически extends
две черты, а именно Product
и Serializable
.
Product
признак расширяется как case class
является алгебраическим типом данных с тип продукта.
Serializable
расширена так, что case class
можно рассматривать как чистые данные, то есть способные сериализоваться.
В отличие от case class
Dog
и Cat
, ваша черта Animal
не распространяется на Product
или Serializable
. Следовательно, подпись типа вы видите.
Когда вы объявляете что-то вроде Array(Dog(""), Cat(""))
, scalac необходимо вывести одиночный верхний тип, который может представлять все элементы заданного массива.
Вот почему выводный тип Product with Serializable with Animal
, поскольку Animal
не расширил Product
и Serializable
, в то время как case class
сделал неявно.
Чтобы обойти этот вывод, вы можете либо сделать тип явным с помощью Animal
, либо сделать Animal
extend Product
и 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
Все классы классов в Scala обладают несколькими свойствами:
- Они автоматически расширят черту
Product
, и для них будет предоставлена реализация по умолчанию, так как они могут рассматриваться как декартово произведение N записей.
- Они будут расширяться
Serializable
, поскольку они могут быть сериализованы из коробки (как выбор дизайна).
- Они будут иметь реализацию
hashCode
и equals
, предоставленную компилятором, которая поддерживает сопоставление с шаблоном
- Они будут предоставлять методы
apply
и unapply
для компоновки и разложения типа.
Классы классов также являются Scala способ выражения Алгебраический тип данных, а точнее Тип продукта. Кортежи также являются типом продукта, и поэтому они также расширяют черту Product
.
Когда вы используете два класса case с общим признаком, компилятор Scala будет использовать алгоритм определения типа типа, чтобы попытаться найти наилучшее совпадающее разрешение для Array
.
Если вы хотите избежать этой детали реализации, вы можете указать, что ваша черта явно расширяет эти черты:
sealed trait Animal extends Product with Serializable
Ответ 3
Все классы case автоматически расширяют Product
и Serializable
. Это выглядит уродливо? да.
В принципе, Product
можно рассматривать как разнородные коллекции. Все классы продуктов, а именно. (Product1, Product2...) расширяет Product
, который содержит некоторые распространенные методы для использования, такие как productArity
, productElement
и т.д.
Подобным классам классов другие типы, которые расширяются Product
, это List
, Tuple
и т.д.
Из моего рабочего листа 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
Подробнее смотрите здесь.