2012-08-26 9 views
8

Vui lòng xem xét mã này:Làm thế nào tôi có thể nhận được đối tượng thực tế được đề cập đến bởi sự phản ánh Scala 2.10?

object ResponseType extends Enumeration { 
    val Listing, Album = Value 
} 

Tôi có thể lấy Symbol đề cập đến đối tượng này như sau:

import reflect.runtime.universe._ 
val s = typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol 

Bây giờ, có biểu tượng này, làm thế nào tôi có thể nhận được các đối tượng thực tế ResponseType?

Trả lời

13
scala> val moduleClass = typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol 
moduleClass: reflect.runtime.universe.Symbol = object ResponseType 

scala> val module = moduleClass.owner.typeSignature.member(moduleClass.name.toTermName) 
module: reflect.runtime.universe.Symbol = object ResponseType 

scala> reflect.runtime.currentMirror.reflectModule(module.asModule).instance 
res9: Any = ResponseType 

Bây giờ, một số giải thích là theo thứ tự, vì chúng tôi không thể tóm tắt chi tiết trong API công khai.

Đối với mỗi object Scala tạo lớp cơ bản đại diện cho chữ ký của nó, được gọi nội bộ là lớp học mô-đun. Ví dụ: nếu bạn biên dịch object C trình biên dịch sẽ tạo ra C$.class. Đó chính xác là lớp mô-đun.

Lưu ý rằng các lớp mô-đun khác với các lớp đồng hành. Giả sử, đối với case class C, trình biên dịch sẽ tạo ra ba biểu tượng: type C, term C và (một số khác) type C, trong đó type C đầu tiên đại diện cho lớp C (chứa bản sao được tạo tự động, productPrefix, productArity, v.v.) đối tượng C (chứa nhà máy được tạo tự động, trình trích xuất v.v ...). Sẽ không có bất kỳ xung đột tên nào, vì lớp mô-đun không được thêm trực tiếp vào bảng biểu tượng và chỉ có sẵn qua <module>.moduleClass.


Vì vậy, những gì bạn thực sự nhận được từ câu typeOf[ResponseType.Value].asInstanceOf[TypeRef].pre.typeSymbol là biểu tượng viết tắt của một lớp mô-đun. Không có hàm nào trong API sẽ đưa bạn đến một biểu tượng mô-đun từ một lớp mô-đun. Bên trong trình biên dịch chắc chắn là một, nhưng chúng tôi quyết định không để lộ chi tiết thực hiện này, bởi vì nó có thể thay đổi rất sớm.

Để truy cập vào mô-đun nguồn, bạn cần truy cập owner, xem trong danh sách các thành viên và tìm kiếm đối tượng có cùng tên với lớp mô-đun. Đó chính xác là những gì moduleClass.owner.typeSignature.member(moduleClass.name.toTermName). Một lưu ý nhỏ là nếu trong cùng một phạm vi bạn có một phương thức có cùng tên, thì member sẽ trả về một biểu tượng quá tải và bạn sẽ cần phải làm một cái gì đó như .member(...).suchThat(_.isModule).

Sau đó là một miếng bánh.


Chỉnh sửa. Thực ra chúng tôi đang nghĩ đến việc giới thiệu ClassSymbol.module sẽ trả về biểu tượng mô đun nguồn cho lớp mô-đun và NoSymbol nếu không. Rất có thể điều này sẽ kết thúc trong RC1. Theo dõi ghi chú phát hành.

+0

Làm cách nào để tôi biết rằng bạn có thể trả lời câu hỏi đó không?) –

+3

Tại sao cần phải truyền? Tôi coi 'asInstanceOf' là một sự thừa nhận thất bại, và một lỗi đang chờ xảy ra. –

+0

Ký pháp thay thế sẽ là: 'val TypeRef (pre, _, _) = typeOf [...]; val moduleClass = pre.typeSymbol'. –