2012-09-29 9 views
6

Tôi đang học khái niệm biểu hiện của Scala và tôi có một sự hiểu biết cơ bản về cách sử dụng nó trong một số trường hợp đơn giản. Câu hỏi của tôi là gì OptNanifestNoManifest cho? Tôi chưa bao giờ thấy rồi sử dụng. Ai đó có thể đưa ra một ví dụ khi chúng cần thiết/hữu ích không?OptManifest và NoManifest của Scala là gì?

(Tôi thấy rằng Scala 2.10 thay thế các khái niệm về Manifest s với TypeTags nhưng cho đến 2.10 là cuối cùng chúng ta phải sử dụng Manifest s.)

Trả lời

6

Giả sử chúng ta có những điều sau lớp trường hợp và loại bí danh:

scala> case class Foo[A](a: A) 
defined class Foo 

scala> type F = Foo[_] 
defined type alias F 

Chúng ta có thể bây giờ (không phải là rất hữu ích) tạo ra một danh sách những thứ kiểu F:

scala> val foos: List[F] = List(Foo(1), Foo("a"), Foo('a)) 
foos: List[F] = List(Foo(1), Foo(a), Foo('a)) 

Và chúng ta có thể tắt chức năng này vào một mảng:

scala> foos.toArray 
res0: Array[F] = Array(Foo(1), Foo(a), Foo('a)) 

Vì vậy, rõ ràng trình biên dịch có thể tìm thấy những biểu hiện nó cần như một tham số ngầm đến toArray phương pháp trên List. Nhưng nếu chúng ta yêu cầu một đồng bằng cũ Manifest cho F, chúng tôi nhận được một lỗi:

scala> manifest[F] 
<console>:11: error: overloaded method value classType with alternatives: 
    (prefix: scala.reflect.Manifest[_],clazz: Class[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and> 
    (clazz: Class[F],arg1: scala.reflect.Manifest[_],args: scala.reflect.Manifest[_]*)scala.reflect.Manifest[F] <and> 
    (clazz: Class[_])scala.reflect.Manifest[F] 
cannot be applied to (java.lang.Class[Foo[_$1]], scala.reflect.Manifest[_$1]) 
       manifest[F] 

Vì vậy, rõ ràng là trình biên dịch là có vấn đề khi dùng biểu hiện để đại diện cho ký tự đại diện trong loại bí danh của chúng tôi.

Lý do toArray hoạt động là nó dự kiến ​​là ClassManifest, không chỉ là Manifest. Và trên thực tế, chúng tôi có thể nhận được ClassManifest cho F không có vấn đề gì, chính xác vì ClassManifest sử dụng OptManifest để thể hiện các đối số loại — không giống như Manifest, đối số kiểu của nó chỉ là những thứ khác thuộc loại Manifest.

scala> classManifest[F] 
res2: ClassManifest[F] = Foo[<?>] 

Đó <?> là chuỗi đại diện của NoManifest. Nó đóng vai trò là None ở đây, cho phép trình biên dịch đại diện cho thông tin lớp về loại F (đó là tất cả chúng ta cần để tạo một mảng, may mắn thay), mà không nói bất cứ điều gì về các đối số kiểu của F ngoài "không, tôi có thể" t mô hình đó ".