2012-10-11 26 views
21

Sử dụng thẻ loại, tôi có thể nhìn thấy các thông số của một số loại:Tìm tham số kiểu thông qua phản chiếu trong Scala 2.10?

scala> import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.universe._ 

scala> typeOf[List[Int]] 
res0: reflect.runtime.universe.Type = List[Int] 

Nhưng tôi chỉ không thể khá tìm ra cách để lập trình nhận được rằng "Int" ra khỏi đó, trong một Cách chung.

(Tôi đã đi lang thang trong REPL trong một giờ, thử hoán vị trên Type, để xem những gì tôi có thể có được từ nó ... Tôi nhận được rất nhiều thứ cho biết đây là "Danh sách", nhưng may mắn khi thấy rằng "Int"! Và tôi không thực sự muốn phân tích cú pháp đầu ra toString() ...)

Daniel Sobral có tổng quan nhanh (như thường lệ) here, trong đó anh ta nhận được tantalizingly gần với những gì tôi đang tìm kiếm, nhưng (rõ ràng) chỉ khi bạn xảy ra để biết, cho rằng lớp học cụ thể, một số phương pháp cụ thể có loại có thể được thẩm vấn:

scala> res0.member(newTermName("head")) 
res1: reflect.runtime.universe.Symbol = method head 

scala> res1.typeSignatureIn(res0) 
res2: reflect.runtime.universe.Type = => Int 

Nhưng tôi hy vọng một cái gì đó tổng quát hơn, không liên quan đến việc rooting xung quanh trong danh sách các phương thức đã khai báo và hy vọng rằng một trong số chúng sẽ nắm bắt (và do đó tiết lộ) thông tin kiểu hiện tại của thẻ ở đâu đó.

Nếu Scala có thể dễ dàng in "Danh sách [Int]", tại sao lại khó phát hiện phần "Int" đó - mà không cần phải khớp mẫu? Hoặc tôi chỉ thiếu một cái gì đó thực sự, thực sự rõ ràng?

scala> res0.typeSymbol.asInstanceOf[ClassSymbol].typeParams 
res12: List[reflect.runtime.universe.Symbol] = List(type A) 

scala> res12.head.typeSignatureIn(res0) 
res13: reflect.runtime.universe.Type = 

Grr ...

+0

Dưới đây là một tổ chức phi câu trả lời: với M7 ít nhất bạn có thể nhận được các đối số loại bằng cách đúc một nội API: 'typeOf [Danh sách [Int]]. AsInstanceOf [scala.reflect.internal.Types $ TypeApiImpl] .typeArguments'. –

+0

Thông minh! Cảm ơn. – Tim

Trả lời

14

Đáng buồn thay, tôi không nghĩ rằng có một phương pháp mà sẽ cung cấp cho bạn các thông số, nhưng bạn có thể có được giữ của họ theo cách này:

Welcome to Scala version 2.10.0-20121007-145615-65a321c63e (Java HotSpot(TM) 64-Bit Server VM, Java 1.6.0_35). 
Type in expressions to have them evaluated. 
Type :help for more information. 

scala> import scala.reflect.runtime.universe._ 
import scala.reflect.runtime.universe._ 

scala> typeOf[List[Int]] 
res0: reflect.runtime.universe.Type = scala.List[Int] 

scala> res0 match { case TypeRef(_, _, args) => args } 
res1: List[reflect.runtime.universe.Type] = List(Int) 

scala> res1.head 
res2: reflect.runtime.universe.Type = Int 

Chỉnh sửa Đây là một cách khá đẹp để đạt được điều tương tự (theo sau discussion on scala-internals):

scala> res0.asInstanceOf[TypeRefApi].args 
res1: List[reflect.runtime.universe.Type] = List(Int) 
+0

Điều này đã được thảo luận trong danh sách gửi thư scala-internals ở đây: https://groups.google.com/forum/#!msg/scala-internals/R1iZXfotqds/zqq8QjMJj74J –

+0

Điều đó dường như làm điều đó! - Mặc dù (tham khảo liên kết của bạn) Tôi chia sẻ unease của bạn là tốt! Tôi muốn chỉ ra kinh nghiệm của chính mình ở đây như là một lý lẽ về việc tại sao điều này vi phạm nguyên tắc của sự kinh ngạc nhất. – Tim

+0

https://groups.google.com/d/topic/scala-internals/56KRF98Mdjo/discussion –

16

Bắt đầu với Scala 2.11, bạn chỉ có thể sử dụng:

yourGenericType.typeArgs.head 

Xem số macros changelog điểm 14.

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