В Scala 2.10 как я могу сгенерировать класс из строки (возможно, используя Toolbox api) позже, чтобы создать экземпляр Scala reflection?
Создание класса из строки и создание экземпляра в Scala 2.10
Ответ 1
В наборах инструментов компиляции W.r.t могут выполняться выражения expression = return, но не результирующие классы или файлы/массивы байтов с результатами компиляции.
Однако все же можно добиться того, чего вы хотите, поскольку в Scala легко перейти от уровня уровня к уровню значения с помощью неявных значений:
Edit. В 2.10.0-RC1 некоторые методы ToolBox
были переименованы. parseExpr
теперь просто parse
, а runExpr
теперь называется eval
.
scala> import scala.reflect.runtime._ // requires scala-reflect.jar
// in REPL it implicitly added
// to the classpath
// but in your programs
// you need to do this on your own
import scala.reflect.runtime
scala> val cm = universe.runtimeMirror(getClass.getClassLoader)
cm @ 41d0fe80: reflect.runtime.universe.Mirror = JavaMirror with scala.tools.nsc.interpreter.IMain$TranslatingClassLoader...
scala> import scala.tools.reflect.ToolBox // requires scala-compiler.jar
// in REPL it implicitly added
// to the classpath
// but in your programs
// you need to do this on your own
import scala.tools.reflect.ToolBox
scala> val tb = cm.mkToolBox()
tb: scala.tools.reflect.ToolBox[reflect.runtime.universe.type] = [email protected]
scala> tb.runExpr(tb.parseExpr("class C; scala.reflect.classTag[C].runtimeClass"))
res2: Any = class __wrapper$1$f9d572ca0d884bca9333e251c64e980d$C$1
Обновление # 1. Если вам не нужен java.lang.Class и просто нужно создать экземпляр скомпилированного класса, вы можете написать new C
непосредственно в строке, представленной в runExpr
.
Обновление №2. Также возможно, что runExpr
использует настраиваемое сопоставление от имен переменных до значений времени выполнения. Например:
scala> val build = scala.reflect.runtime.universe.build
build: reflect.runtime.universe.BuildApi = [email protected]
scala> val x = build.setTypeSignature(build.newFreeTerm("x", 2), typeOf[Int])
x: reflect.runtime.universe.FreeTermSymbol = free term x
scala> tb.runExpr(Apply(Select(Ident(x), newTermName("$plus")), List(Literal(Constant(2)))))
res0: Any = 4
В этом примере я создаю свободный термин, который имеет значение 2 (значение не должно быть примитивным - это может быть ваш пользовательский объект) и привязывать к нему идентификатор. Это значение затем используется как-есть в коде, который компилируется и запускается с помощью панели инструментов.
В примере используется ручная сборка АСТ, но можно написать функцию, которая анализирует строку, обнаруживает несвязанные идентификаторы, просматривает значения для них в некотором сопоставлении и затем создает соответствующие свободные термины. Там нет такой функции в Scala 2.10.0.