如何在 Scala 中反射性地参数化泛型类型?
How to reflectively parameterise a generic type in Scala?
如何使用反射在 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](...)
)。
Scala 和 Java 编译器都实现了带有类型擦除的泛型。这意味着当源代码转换为 JVM 字节码时,泛型子类型的所有类型信息都会丢失。如果通用 class 本身不包含 ClassTag
或类似的嵌入信息,那么您无法在 运行 时获得 class。
您可以尝试创建一个 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
}
如何使用反射在 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](...)
)。
Scala 和 Java 编译器都实现了带有类型擦除的泛型。这意味着当源代码转换为 JVM 字节码时,泛型子类型的所有类型信息都会丢失。如果通用 class 本身不包含 ClassTag
或类似的嵌入信息,那么您无法在 运行 时获得 class。
您可以尝试创建一个 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
}