2016-04-10 14 views
13

uczę Scala i próbował poniższego formularza Scala Cookbook:Scala klasa sprawa powiększenia wyrobów z Serializable

trait Animal 
trait FurryAnimal extends Animal 
case class Dog(name:String) extends Animal 
case class Cat(name:String) extends Animal 

Teraz, kiedy nie dalej jako:

val x = Array(Dog("Fido"),Cat("Felix")) 

wykazać wynik:

x:Array[Product with Serializable with Animal] = Array(Dog(Fido),Cat(Felix)) 

Chociaż wiem, że klasa przypadków jest pomieszana z cechą produktu

Co ja nie otrzymuję to: Product with Serializable with Animal

Jak na moje rozumienie produkt ma coś wspólnego z Pattern Matching

zrobiłem google ale nie dostał anything.Please Pomoc aby uzyskać szczegółowy koncept.

Dzięki

+0

Hej, to heterogeniczna tablica i oba elementy rozciągają się na Zwierzę, stąd na Zwierzę. Jeśli umieścisz obie te klasy case w innej klasie case, a następnie dodasz tę klasę case do tablicy. otrzymasz tablicę klasy case. Sam szukałem dobrej lektury tego produktu z Serializable przez jakiś czas .. Ale nie znalazłem. Może ktoś może oczyścić nasze myśli.! –

+0

http://underscore.io/blog/posts/2015/06/04/more-on-sealed.html –

+0

również https://github.com/scala/scala-abide/issues/41 –

Odpowiedz

25

Jest to oczekiwane zachowanie ze względu na sposób działania case class. case class automatycznie extends dwie cechy, a mianowicie Product i Serializable.

Product cecha jest przedłużana jako case class jest algebraic data type z product type.

Serializable cecha jest przedłużona, dzięki czemu case class może być traktowane jako czyste dane - tj. Może być serializowane.

przeciwieństwie case classDog i Cat, twoja cecha Animal nie rozciąga Product lub Serializable. Stąd widać podpis typu.

Po zadeklarowaniu czegoś takiego jak Array(Dog(""), Cat("")), skalak musi wywnioskować pojedynczy top type, który może reprezentować wszystkie elementy danej tablicy.

Dlatego wywnioskować typ jest Product with Serializable with Animal jak Animal nie rozciągają Product ani Serializable natomiast case class zrobił niejawnie.

celu obejścia tego wnioskowania, można dokonać typ wyraźny przez Animal lub dokonać Animal przedłużyć Product i 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

Dziękuję za wyjaśnienie i linki do wiki, które wyjaśniły mi się za pomocą modelu matematycznego. – optional

9

Wszystkie klasy przypadków w Scala posiadać kilka właściwości:

  1. Będą automatycznie rozciągają cechę Product a domyślna implementacja będzie przewidziane dla nich, ponieważ mogą one być postrzegane jako a Cartesian Product of N records.
  2. Będą one przedłużać Serializable, ponieważ można je serializować z pudełka (jako wybór projektu).
  3. będą one implementację hashCode i equals dostarczane przez kompilator, co wspomaga z wzorem pasującym
  4. będą one zapewniać apply i unapply sposobów, kompozycji i rozkładu typu.

Klasy przypadków to także sposób wyrażania przez Scala wartości Algebraic Data Type, a dokładniej: Product Type. Tuples are also a product type, i jako takie rozszerzają także cechę Product.

Gdy używasz dwóch klas przypadków o wspólnej cechie, kompilator scala użyje swojego algorytmu oceny typu, aby znaleźć najlepszą pasującą rozdzielczość dla Array.

Jeśli chcesz uniknąć widząc ten szczegół realizacji, można mieć cecha wyraźnie przedłużyć te cechy:

sealed trait Animal extends Product with Serializable 
0

Wszystkie klasy przypadków automatycznie przedłużyć Product i Serializable. Wygląda brzydko? tak. Zasadniczo, Product można postrzegać jako kolekcje heterogeniczne. Wszystkie klasy produktów viz. (Product1, Product2 ...) rozszerza Product, który zawiera niektóre popularne metody używania, takie jak productArity, productElement itp.

klas Podobnie jak przypadku innych typów, który rozciąga ProductList, Tuple itp

Z mojego scala arkuszu

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 

Szczegółowe wyglądać here.