从字符串生成一个类并在 Scala 2.10 中实例化它

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12122939/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-22 04:27:55  来源:igfitidea点击:

Generating a class from string and instantiating it in Scala 2.10

scalareflectiontoolboxscala-2.10

提问by Nikita Volkov

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?

在 Scala 2.10 中,如何从字符串(可能使用 Toolbox api)生成一个类,以便稍后使用 Scala 的反射进行实例化?

回答by Eugene Burmako

W.r.t compilation toolboxes can only run expressions = return values, but not resulting classes or files/byte arrays with compilation results.

Wrt 编译工具箱只能运行表达式 = 返回值,但不能运行带有编译结果的类或文件/字节数组。

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:

然而,仍然有可能实现您想要的,因为在 Scala 中使用隐式值很容易从类型级别转到值级别:

Edit. In 2.10.0-RC1 some methods of ToolBoxhave been renamed. parseExpris now just parse, and runExpris now called eval.

编辑。在 2.10.0-RC1 中,某些方法ToolBox已重命名。parseExpr现在只是parserunExpr现在被称为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$f9d572ca0d884bca9333e251c64e980d$C

Update #1. If you don't need a java.lang.Class and just need to instantiate the compiled class, you can write new Cdirectly in the string submitted to runExpr.

更新#1。如果不需要java.lang.Class,只需要实例化编译后的类,new C直接在提交到的字符串中写即可runExpr

Update #2. It is also possible to have runExpruse custom mapping from variable names to runtime values. For example:

更新#2。也可以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

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.

在本例中,我创建了一个值为 2 的自由项(该值不必是原始值 - 它可以是您的自定义对象)并将标识符绑定到它。然后在由工具箱编译和运行的代码中按原样使用该值。

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.

该示例使用手动 AST 汇编,但可以编写一个函数来解析字符串,找出未绑定的标识符,在某些映射中查找它们的值,然后创建相应的自由项。但是 Scala 2.10.0 中没有这样的功能。