从string生成一个类,并在Scala 2.10中实例化它
在Scala 2.10中,我怎样从string(可能使用Toolbox api)生成一个类,然后用Scala的reflection来实例化?
Wrt编译工具箱只能运行expression式=返回值,但不能生成带有编译结果的类或文件/字节数组。
但是仍然有可能实现你想要的,因为在Scala中,使用隐式值很容易从types级别转换为值级别:
编辑 。 在2.10.0-RC1中ToolBox
某些方法已经被重命名了。 parseExpr
现在只是parse
, runExpr
现在被称为eval
。
scala> import scala.reflect.runtime._ // requires scala-reflect.jar // in REPL it's 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's 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] = scala.tools.reflect.ToolBoxFactory$ToolBoxImpl@3a962da5 scala> tb.runExpr(tb.parseExpr("class C; scala.reflect.classTag[C].runtimeClass")) res2: Any = class __wrapper$1$f9d572ca0d884bca9333e251c64e980d$C$1
更新#1。 如果你不需要一个java.lang.Class,只需要实例化编译的类,就可以直接在提交给runExpr
的string中编写new C
runExpr
。
更新#2。 runExpr
也可以使用从variables名到运行runExpr
自定义映射。 例如:
scala> val build = scala.reflect.runtime.universe.build build: reflect.runtime.universe.BuildApi = scala.reflect.internal.BuildUtils$BuildImpl@50d5afff 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
在这个例子中,我创build了一个值为2的免费术语(该值不一定是原语 – 它可以是您的自定义对象)并将标识符绑定到它。 然后,该值将被原样用于由工具箱编译和运行的代码。
该示例使用手动AST汇编,但可以编写一个函数来parsingstring,找出未绑定的标识符,在某些映射中查找它们的值,然后创build相应的空白项。 虽然在Scala 2.10.0中没有这样的function。