Как правильно определить общий тип в Scala? - PullRequest
0 голосов
/ 25 июня 2018

Как я могу реализовать следующий псевдокод в 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

Примечание: I не не имеет доступа к типу A во время компиляции, следовательно, _.Все решение должно быть выполнено рефлексивно (например, у меня не может быть parameterizeFoo[A : ClassTag](...)).

Ответы [ 2 ]

0 голосов
/ 26 июня 2018

Вы можете попытаться создать 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
}
0 голосов
/ 25 июня 2018

И компиляторы Scala, и Java реализуют обобщения с стиранием типов. Это означает, что вся информация о типах для подтипов универсальных элементов теряется при преобразовании исходного кода в байтовый код JVM. Если сам универсальный класс не содержит ClassTag или подобную внедренную информацию, то вы не можете получить класс во время выполнения.

...