我有两个班级:
class Base[A]{
def doSome:A
}
class StringImpl extends Base[String]
如何推断(没有清单,只有反射分析)类StringImpl中的泛型类型是String? (在实际情况下,遗传结构可能更复杂,例如)
答案 0 :(得分:3)
使用scala运行时反射(isInstanceOf
不适用于已删除的类型 - 它始终返回true
):
typeOf[StringImpl] <:< typeOf[Base[String]] //true
typeOf[StringImpl] <:< typeOf[Base[Int]] //false
请参阅:http://www.scala-lang.org/api/2.11.7/scala-reflect/#scala.reflect.api.Types $ TypeApi
val tp = typeOf[StringImpl]
tp.baseType(tp.baseClasses(1)).typeArgs
res17_4: List[reflect.runtime.package.universe.Type] = List(String)
它允许您访问类型参数等以获得更复杂的案例。
更新。对于ClassSymbol
,您可以使用typeSignature
方法:
tp.typeSymbol.typeSignature
res19_5: reflect.runtime.package.universe.Type = Helper.this.Base[String] {
def <init>(): Helper.this.StringImpl
def doSome: String
}
另外,对于宏(如果你不想要明显的WeakTypeTag
解决方案):
import c.universe._
val TypeApply(_, List(typeTree)) = c.macroApplication
//you can analyze typeTree here
Scala: Get type name without runtime reflection and without type instance
一般答案
通用类型在JVM中被擦除,因此默认情况下在运行时没有存储信息 - 在一般情况下,没有ClassTag / TypeTag在运行时“物理上”无法获取擦除类型(只能在子类中探索方法/成员签名)这样的存在)。但是,您始终可以进行编译时检查,例如:
abstract class Base{
type A
def doSome:A
}
class StringImpl extends Base{
type A = String
def doSome:A = "aaa"
}
implicitly[StringImpl#A =:= String]
答案 1 :(得分:0)
我认为你可以获得doSome
方法返回类型的通用类型 A 没有清单(因为没有访问父类),例如:
new StringImpl().getClass.getMethod("doSome").getReturnType.getSimpleName
> String