从字符串生成类并在Scala 2.10中实例化它 [英] Generating a class from string and instantiating it in Scala 2.10
问题描述
在Scala 2.10中,如何稍后通过字符串(可能使用Toolbox api)从字符串生成一个类,以使用Scala的反射进行实例化?
In Scala 2.10 how do I generate a class from string (probably, using the Toolbox api) later to be instantiated with Scala's reflection?
推荐答案
W.r.t编译工具箱只能运行expressions =返回值,而不能生成带有编译结果的类或文件/字节数组.
W.r.t compilation toolboxes can only run expressions = return values, but not resulting classes or files/byte arrays with compilation results.
但是仍然可以实现您想要的,因为在Scala中,使用隐式值从类型级别转换到值级别非常容易:
However it's still possible to achieve what you want, since in Scala it's so easy to go from type level to value level using implicit values:
修改.在2.10.0-RC1中,ToolBox
的某些方法已重命名. parseExpr
现在只是parse
,而runExpr
现在称为eval
.
Edit. In 2.10.0-RC1 some methods of ToolBox
have been renamed. parseExpr
is now just parse
, and runExpr
is now called 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
的字符串中直接编写new C
.
Update #1. If you don't need a java.lang.Class and just need to instantiate the compiled class, you can write new C
directly in the string submitted to runExpr
.
更新#2. runExpr
也可以使用从变量名到运行时值的自定义映射.例如:
Update #2. It is also possible to have runExpr
use custom mapping from variable names to runtime values. For example:
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
在此示例中,我创建一个值为2的自由项(该值不必是原始值,它可以是您的自定义对象),并将标识符绑定到该值.然后,该值将按原样在由工具箱编译和运行的代码中使用.
In this example I create a free term that has a value of 2 (the value doesn't have to be a primitive - it can be your custom object) and bind an identifier to it. This value is then used as-is in the code that is compiled and run by a toolbox.
该示例使用手动AST汇编,但是可以编写一个函数来解析字符串,找出未绑定的标识符,在某些映射中查找它们的值,然后创建相应的自由术语.但是在Scala 2.10.0中没有这样的功能.
The example uses manual AST assembly, but it's possible to write a function that parses a string, finds out unbound identifiers, looks up values for them in some mapping and then creates corresponding free terms. There's no such function in Scala 2.10.0 though.
这篇关于从字符串生成类并在Scala 2.10中实例化它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!