在 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 的实例(它在脚本引擎中明确实现)?