#scala #reflection #types #casting
#scala #отражение #типы #Кастинг
Вопрос:
У меня есть
trait T
class C extends T
компилируется в файлы .class. Запустите scala с -cp <...>
, чтобы иметь T
доступный тип. Затем загрузите класс C, используя отражение:
val loader = ScalaClassLoader fromURLs (/* List[URL] */)
val anyC = loader.tryToInitializeClass("C") getOrElse (/* throw something */)
val classC = anyC.asInstanceOf[Class[T]]
Как я могу привести classC.newInstance
к типу T
, например
val objC = classC.newInstance.asInstanceOf[T]
// yields java.lang.ClassCastException: C cannot be cast to T
Ответ №1:
Вы должны загружать класс C
из другого загрузчика классов, отличного от T
загружаемого.
Вы поместили оба T
и C
в путь к классу REPLs, поэтому одним из вариантов может быть загрузка C
через системный загрузчик классов. Пример сеанса REPL,
scala> val loader = scala.tools.nsc.util.ScalaClassLoader.getSystemLoader
loader: scala.tools.nsc.util.ScalaClassLoader =
scala.tools.nsc.util.ScalaClassLoader$$anon$1@985d2e0
scala> val anyC = loader.tryToInitializeClass("C") getOrElse (sys.error("Boom"))
anyC: Class[Nothing] = class C
scala> val classC = anyC.asInstanceOf[Class[T]]
classC: Class[T] = class C
Примечание. на самом деле это уже не вопрос, специфичный для Scala.
Комментарии:
1. Итак, есть ли какой-нибудь способ «объединить» эти два загрузчика классов?
2. Это действительно зависит от того, что вы пытаетесь сделать. Я отредактировал ответ, чтобы показать один вариант.
3. Да, я хочу проверить, реализовал ли пользователь
trait
предоставленное. Я нашел способval loader = ScalaClassLoader fromURLs (/* List[URL] */, classOf[T].getClassLoader)
, вот и все. Спасибо за вашу помощь!