从字符串生成类并在Scala 2.10中实例化它 [英] Generating a class from string and instantiating it in Scala 2.10

查看:119
本文介绍了从字符串生成类并在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆