Подтвердить что ты не робот

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, но ничего не получил. Пожалуйста, помогите мне детально описать концепцию.

Спасибо

4b9b3361

Ответ 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

Подробнее смотрите здесь.