在Scala中动态创建类,我应该使用解释器吗?

13
我想在 Scala 中运行时创建一个类。目前,只考虑一个简单的情况,我想创建一个具有一些属性的Java bean的等价物,而这些属性我只能在运行时知道。
如何创建 Scala 类?如果有一种编译并在运行时加载它的方式,我愿意从 Scala 源文件中创建它,因为有时我希望向类添加一些复杂的函数。如何做到这一点?
我担心的是,我读到的 Scala 解释器将被限制在加载的解释代码中,以使其对托管解释器的一般应用程序不可用。如果是这样的话,我就不能使用动态加载的 Scala 类。
无论如何,问题是,如何在运行时动态创建 Scala 类并在我的应用程序中使用它。最好的情况是从 Scala 源文件中运行时加载类,类似于 interpreterSource("file.scala"),并将其加载到当前运行时中;第二好的情况是通过调用方法 createClass(...) 在运行时创建它。
感谢您,Phil
1个回答

8
目前没有足够的信息来确定最佳答案,但请记住您正在运行JVM,因此任何Java有效的技术或字节码工程库在此也应该有效。
有数百种可能使用的技术,但最佳选择完全取决于您的确切用例,因为许多不是通用的。以下是一些想法:
- 对于简单的bean,您可以使用map,或者查看apache commons中的DynaBean类。 - 对于更高级的行为,您可以显式调用编译器,然后通过类加载器获取生成的.class文件(这在很大程度上是JSP的工作方式)。 - 在某些情况下,解析器和自定义DSL非常适合。Bean shell脚本也是如此。
请查看ScalaDays视频:http://days2010.scala-lang.org/node/138/146,其中演示了将Scala用作JSR-223兼容的脚本语言的用法。这应涵盖大多数需要在运行时评估Scala的情况。
您还需要查看此电子邮件线程:http://scala-programming-language.1934581.n4.nabble.com/Compiler-API-td1992165.html#a1992165 其中包含以下示例代码:
// We currently call the compiler directly 
// To reduce coupling, we could instead use ant and the scalac ant task 

import scala.tools.nsc.{Global, Settings} 
import scala.tools.nsc.reporters.ConsoleReporter
{ 
  // called in the event of a compilation error 
  def error(message: String): Nothing = ... 

  val settings = new Settings(error) 
  settings.outdir.value = classesDir.getPath 
  settings.deprecation.value = true // enable detailed deprecation warnings 
  settings.unchecked.value = true // enable detailed unchecked warnings 

  val reporter = new ConsoleReporter(settings) 

  val compiler = new Global(settings, reporter) 
  (new compiler.Run).compile(filenames) 

  reporter.printSummary 
  if (reporter.hasErrors || reporter.WARNING.count > 0) 
  { 
             ... 
  } 
} 


val mainMethod: Method = { 
  val urls = Array[URL]( classesDir.toURL ) 

  val loader = new URLClassLoader(urls) 

  try { 
    val clazz: Class = loader.loadClass(...) 

    val method: Method = clazz.getMethod("main", Array[Class]( classOf[Array[String]] )) 
    if (Modifier.isStatic(method.getModifiers)) { 
       method 
    } else { 
      ... 
    } 
  } catch { 
    case cnf: ClassNotFoundException => ... 
    case nsm: NoSuchMethodException => ... 
  } 
} 

mainMethod.invoke(null, Array[Object]( args )) 

我想从Scala源代码创建它,假设我有Scala源代码作为字符串,我该怎么做? - Phil
除了上述内容外,以下链接也可能有所帮助(我并不自称是该领域的专家): http://scala-programming-language.1934581.n4.nabble.com/Compiling-a-Scala-Snippet-at-run-time-td2000704.html - user127386
我在使用这段代码时遇到了麻烦,特别是我不明白为什么你会在导入之后放置一个代码块。这段代码完整吗?还是有一些行缺失了? - mariosangiorgio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接