1

在 2.11 Milestone 7 中使用 Scala 脚本引擎,我如何从脚本引擎中获取类型化的值?我收到诸如“mypackage.Holler 无法转换为 mypackage.Holler”之类的错误消息。

这是用例(简化为基本内容)。我想使用脚本来准备和配置我将在主程序中处理的标准类型的对象。我有一个特点:

package mypackage

trait Holler {
  def shout: Unit
}

我在 Scala 中有一个用户脚本,保存在 /home/me/Foo.scala 文件中

object Foo extends mypackage.Holler {
  def shout: Unit = println("Hello World!")
}

当我使用 IMain.eval(Reader) 运行此脚本时,我希望对象 Foo 将被返回,因为它是最后一条语句的结果。这是一个程序,包括几个有用的打印输出来运行脚本:

package mypackage

import javax.script.ScriptEngineManager
import scala.tools.nsc.interpreter.IMain

object Runner {
  def main(args: Array[String]): Unit = {
    //  Create the script engine
    val javaxEngine = new ScriptEngineManager().getEngineByName("scala")
    val scalaEngine = javaEngine.asInstanceOf[IMain]

    // Configure script engine to use the Java classpath
    val useJavaClassPath = scalaEngine.settings.usejavacp.tryToSet(List("true"))
    println("Use Java CP? " + useJavaClassPath)

    val script = new java.io.FileReader("/home/me/Foo.scala")
    val result = scalaEngine.eval(script)
    println("Script Result Type: " + result.getClass.getName)
    println("Defined Symbols: " + scalaEngine.definedSymbolList)
    val myHoller = result.asInstanceOf[mypackage.Holler]
  }
}

该脚本在脚本引擎下运行得很好。但结果不能投给霍勒。该程序的输出如下:

Use Java CP? Some(List(true))
Script Result Type: $line3.$read$$iw$$iw$Foo$
Defined Symbols: List(value engine, object iw$Foo)
Exception in thread "main" java.lang.ClassCastException: $line3.$read$$iw$$iw$Foo$ cannot be cast to mypackage.Holler

这告诉我脚本引擎成功识别了类路径,并且正在构造 Foo 对象。但是脚本中的特征 mypackage.Holler(来自公共类路径)与主程序中的特征 mypackage.Holler 不同。

如果我将以下行添加到脚本中:

Foo.shout
val result: Holler = Foo

我懂了:

  • 正在执行的喊叫方法(“Hello World!”打印出来),
  • “结果”被添加到定义的符号列表中
  • 结果显然与 Holler 类型兼容。

我可以将“捕手”对象绑定到脚本引擎。它的代码如下所示:

package mypackage

class Catcher {
  var item: Holler = null
}

我与

val mycatcher = new Catcher
scalaEngine.bind("catcher", mycatcher)
scalaEngine.eval("catcher = Foo")

现在“捕手”出现在脚本引擎的已定义符号列表中,我可以使用捕手通过如下命令进入脚本引擎

scalaScriptEngine.eval("catcher.item = result")

但后来我得到奇怪的“编译时间”ClassCastExceptions 说:

mypackage.Holler cannot be cast to mypackage.Holler

如果我将 Catcher 中的“项目”设为 Any,那么在我这样做之前我不会得到异常

mycatcher.item.asInstanceOf[Holler]

在主程序中。但我仍然得到几乎相同的例外。就好像两个不兼容的类加载器正在同一个类路径中使用。那么,如何从主程序访问 Foo 对象作为 Holler 的实例(它在脚本引擎中明确实现)?

4

0 回答 0