Giả sử rằng tôi có một lớp cha Generic:Trong Scala Reflection, Làm thế nào để có được tham số kiểu generic của một lớp con cụ thể?
class GenericExample[T](
a: String,
b: T
) {
def fn(i: T): T = b
}
và một lớp con cụ thể:
case class Example(
a: String,
b: Int
) extends GenericExample[Int](a, b)
Tôi muốn để có được các thông số loại chức năng "fn" bằng cách phản ánh scala, vì vậy tôi lựa chọn và bộ lọc thông qua các thành viên của nó:
import ScalaReflection.universe._
val baseType = typeTag[Example]
val member = baseType
.tpe
.member(methodName: TermName)
.asTerm
.alternatives
.map(_.asMethod)
.head
val paramss = member.paramss
val actualTypess: List[List[Type]] = paramss.map {
params =>
params.map {
param =>
param.typeSignature
}
}
tôi đã mong scala để cho tôi kết quả chính xác, đó là List(List(Int))
, thay vào đó tôi chỉ g ot chung List(List(T))
crunching qua các tài liệu tôi thấy rằng typeSignature là thủ phạm:
* This method always returns signatures in the most generic way possible, even if the underlying symbol is obtained from an
* instantiation of a generic type.
Và nó cho thấy tôi sử dụng giải pháp thay thế:
def typeSignatureIn(site: Type): Type
Tuy nhiên, kể từ khi lớp Ví dụ không dài hơn chung chung, không có cách nào tôi có thể nhận được trang web từ typeTag [Ví dụ], bất cứ ai có thể đề nghị tôi làm thế nào để có được typeOf [Int] cho chỉ typeTag [Ví dụ]? Hoặc không có cách nào để làm điều đó và tôi phải hoàn nguyên về sự phản chiếu của Java?
Cảm ơn rất nhiều sự giúp đỡ của bạn.
UPDATE: Sau một số thử nghiệm nhanh chóng tôi thấy rằng thậm chí MethodSymbol.returnType không hoạt động như mong đợi, đoạn code sau:
member.returnType
cũng mang lại T
, annd nó không thể được sửa chữa bởi asSeenFrom, như đoạn mã sau không làm thay đổi kết quả:
member.returnType.asSeenFrom(baseType.tpe, baseType.tpe.typeSymbol.asClass)
Thậm chí trước khi thực sự đọc câu hỏi của bạn. Trong suốt toàn bộ kinh nghiệm của tôi với scala, một trong những khái niệm cốt lõi của nó là ủy thác càng nhiều càng tốt cho trình biên dịch. Vì vậy, phản ánh không phải là một trong những điều bạn sẽ làm trong scala. Tuy nhiên, bạn có thể sử dụng Macro hoặc ngữ cảnh (Manifests và ClassManifests) – caeus
là Manifest trong quá trình không được chấp nhận? Và ClassManifest được đổi tên thành ClassTag? Tôi hy vọng ít nhất tôi cũng có thể lấy được ClassTag bị xóa khỏi phương thức, nhưng vẫn không thể làm như vậy. – tribbloid