如何在Scala REPL中重新加载类或包?

时间:2010-03-18 17:19:10

标签: scala read-eval-print-loop

我几乎总是有一个或两个Scala REPL会话,这使得为Java或Scala类提供快速测试非常容易。但是,如果我更改一个类并重新编译它,REPL将继续加载旧的类。有没有办法让它重新加载类,而不必重新启动REPL?

举一个具体的例子,假设我们有文件Test.scala:

object Test { def hello = "Hello World" }

我们编译它并启动REPL:

~/pkg/scala-2.8.0.Beta1-prerelease$ bin/scala
Welcome to Scala version 2.8.0.Beta1-prerelease
(Java HotSpot(TM) Server VM, Java 1.6.0_16).
Type in expressions to have them evaluated.
Type :help for more information.

scala> Test.hello
res0: java.lang.String = Hello World

然后我们将源文件更改为

object Test {
  def hello = "Hello World"
  def goodbye = "Goodbye, Cruel World"
}

但我们无法使用它:

scala> Test.goodbye
<console>:5: error: value goodbye is not a member of object Test
       Test.goodbye
            ^

scala> import Test;
<console>:1: error: '.' expected but ';' found.
       import Test;

5 个答案:

答案 0 :(得分:40)

如果目标是不必重复以前的命令,则可以选择重新加载类。 REPL具有命令

:replay

重新启动REPL环境并播放所有先前的有效命令。 (跳过无效的,所以如果以前错了,它就不会突然工作。)当重置REPL时,它会重新加载类,所以新命令可以使用重新编译的类的内容(事实上,旧的命令也将使用那些重新编译的类。)

这不是一般解决方案,但是使用可重新计算状态扩展单个会话的有用快捷方式。

注意:这适用于裸Scala REPL。如果你从SBT或其他环境运行它,它可能会或可能不会工作,这取决于SBT或其他环境如何打包类 - 如果你不更新正在使用的实际类路径上的内容,当然它赢了'工作!

答案 1 :(得分:27)

类重新加载不是一个简单的问题。事实上,这是JVM非常困难的事情。你确实有几个选择:

  • 以调试模式启动Scala REPL。 JVM调试器有一些内置的重新加载,可以在方法级别上运行。它对你提供的案例没有帮助,但它会处理一些简单的事情,比如更改方法实现。
  • 使用JRebel(http://www.zeroturnaround.com/jrebel)。 JRebel基本上是一个超级充值的类重装解决方案 JVM。它可以处理 成员添加/删除,新/删除的类,定义更改等。无法处理的唯一事情是类层次结构中的更改(添加超级接口,用于 例)。它不是一个免费工具,但它们提供的补充许可仅限于Scala编译单元。

不幸的是,这些都受到Scala REPL实现细节的限制。我使用JRebel,它通常可以解决问题,但仍然存在REPL不会反映重新加载的类的情况。不过,它总比没有好。

答案 2 :(得分:8)

有一个符合你要求的命令

:load path/to/file.scala

将重新加载scala源文件并重新编译为类,然后您可以重放代码

答案 3 :(得分:6)

这对我有用....

如果您的新源文件Test.scala看起来像这样......

package com.tests

object Test {
  def hello = "Hello World"
  def goodbye = "Goodbye, Cruel World"
}

首先必须将新更改加载到Scala控制台(REPL)。

:load src/main/scala/com/tests/examples/Test.scala

然后重新导入包,以便您可以在Scala控制台中引用新代码。

import com.tests.Test

现在享受您的新代码,而无需重新启动会话:)

scala> Test.goodbye
res0: String = Goodbye, Cruel World

答案 4 :(得分:2)

如果.scala文件位于启动REPL的目录中,则可以省略完整路径,只需添加:load myfile.scala,然后导入。