如何使用反射在Scala中实现以下伪代码?
出于从Guice查找通用类型的目的,我需要这样做:
trait Foo[A]
class FooInt extends Foo[Int]
class FooString extends Foo[String]
bind(new TypeLiteral<Foo<Int>>() {}).to(FooInt.class);
def fooTypeLiteral(paramA: Class[_]): TypeLiteral[_] = ???
val foo = injector.getInstance(fooTypeLiteral(classOf[Int])
// foo: FooInt
注意:我没有在编译时可以访问A
的类型,因此可以访问_
。整个解决方案需要反思地执行(例如,我不能拥有parameterizeFoo[A : ClassTag](...)
)。
答案 0 :(得分:1)
您可以尝试创建一个ParameterizedType
并将其传递给TypeLiteral
的工厂方法:
def fooTypeLiteral(paramA: Class[_]): TypeLiteral[_] = {
TypeLiteral.get(new java.lang.reflect.ParameterizedType() {
def getRawType = classOf[Foo[_]]
def getOwnerType = null
def getActualTypeArguments = Array(paramA)
})
}
如果您只有有限数量的Foo
实现,则可以尝试以下方法:
trait Foo[A]
class FooInt extends Foo[Int]
class FooString extends Foo[String]
val TLFI = new TypeLiteral[Foo[Int]](){}
val TLFS = new TypeLiteral[Foo[String]](){}
bind(TLFI).to(FooInt.class);
bind(TLFS).to(FooString.class);
def fooTypeLiteral(c: Class[_]): TypeLiteral[_] = {
if (c == classOf[Int]) TLFI
else if (c == classOf[String]) TLFS
else throw new Error
}
答案 1 :(得分:0)
Scala和Java编译器都使用类型擦除来实现泛型。这意味着,当源代码转换为JVM字节码时,泛型子类型的所有类型信息都会丢失。如果通用类本身不包含ClassTag
或类似的嵌入式信息,那么您将无法在运行时获取该类。