2016-04-10 16 views
13

tôi đang học scala và cố gắng hình thức sau đây Scala Cookbook:Scala trường hợp lớp mở rộng sản phẩm với Serializable

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

Bây giờ khi tôi đã sau như:

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

nó hiển thị kết quả như sau:

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

Mặc dù tôi biết rằng một trường hợp được trộn lẫn với Đặc điểm sản phẩm

gì tôi không nhận được là: Product with Serializable with Animal

Theo hiểu biết của tôi Sản phẩm có cái gì để làm với mẫu phù hợp với

Tôi đã google nó nhưng đã không nhận được anything.Please Trợ giúp để cho tôi khái niệm chi tiết.

Cảm ơn

+0

Đây là mảng không đồng nhất và cả phần tử mở rộng Động vật, do đó có Động vật. Nếu bạn đặt cả hai lớp trường hợp này vào trong một trường hợp khác và sau đó thêm lớp đó vào mảng đó. bạn sẽ nhận được mảng của lớp vỏ. Tôi đã tự tìm kiếm một bản đọc tốt trên Sản phẩm này với Serializable một thời gian .. Nhưng không tìm thấy. Có lẽ ai đó có thể xóa suy nghĩ của chúng tôi. –

+0

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

+0

cũng https://github.com/scala/scala-abide/issues/41 –

Trả lời

25

Đây là hành vi mong đợi do cách hoạt động của case class. case class tự động extends hai đặc điểm, cụ thể là ProductSerializable.

Product đặc điểm được mở rộng thành case classalgebraic data type với product type.

Serializable đặc điểm được mở rộng sao cho case class có thể được coi là dữ liệu thuần túy - có khả năng được tuần tự hóa.

Không giống như case classDogCat, đặc điểm của bạn Animal không mở rộng Product hoặc Serializable. Do đó chữ ký kiểu bạn thấy.

Khi bạn khai báo một cái gì đó như Array(Dog(""), Cat("")), scalac cần suy ra đơn top type có thể đại diện cho tất cả các phần tử của mảng đã cho.

Đó là lý do loại suy ra là Product with Serializable with Animal như Animal không mở rộng Product cũng không Serializable trong khi case class đã ngầm.

Để làm việc xung quanh suy luận này, bạn có thể làm kiểu tường minh bởi Animal hoặc làm Animal mở rộng 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()) 
+2

Cảm ơn lời giải thích và các liên kết wiki đã làm cho tôi rõ ràng với mô hình toán học. – optional

9

Tất cả các lớp trường hợp trong Scala sở hữu một vài thuộc tính:

  1. Họ sẽ tự động mở rộng Product đặc điểm và thực hiện mặc định sẽ được cung cấp cho họ, vì chúng có thể được xem như là a Cartesian Product of N records.
  2. Họ sẽ mở rộng Serializable vì chúng có thể được tuần tự hóa khỏi hộp (dưới dạng lựa chọn thiết kế).
  3. Họ sẽ có một thực hiện hashCodeequals cung cấp bởi trình biên dịch, mà viện trợ với mô hình phù hợp với
  4. Họ sẽ cung cấp applyunapply phương pháp, cho các thành phần và phân hủy của các loại.

Trường hợp cũng là cách biểu thị của Scala là Algebraic Data Type, cụ thể hơn là Product Type. Tuples are also a product type và do đó chúng cũng mở rộng đặc điểm Product.

Khi bạn sử dụng hai lớp chữ hoa với một đặc điểm chung, trình biên dịch của scala sẽ sử dụng thuật toán suy luận kiểu để cố gắng tìm độ phân giải phù hợp nhất cho số Array.

Nếu bạn muốn tránh nhìn thấy chi tiết thực hiện điều này, bạn có thể có đặc điểm của bạn mở rộng một cách rõ ràng những đặc điểm:

sealed trait Animal extends Product with Serializable 
0

Tất cả các lớp trường hợp tự động mở rộng ProductSerializable. Nó trông xấu xí? Vâng. Về cơ bản, Product có thể được xem dưới dạng bộ sưu tập không đồng nhất. Tất cả các lớp sản phẩm viz. (Product1, Product2 ...) mở rộng Product có chứa một số phương pháp phổ biến để sử dụng như productArity, productElement v.v.

lớp Giống như trường hợp các loại khác mà kéo dài ProductList, Tuple vv

Từ bảng scala tôi,

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 

Để biết chi tiết trông here.

Các vấn đề liên quan