我几乎总是有一个或两个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;
答案 0 :(得分:40)
如果目标是不必重复以前的命令,则可以选择重新加载类。 REPL具有命令
:replay
重新启动REPL环境并播放所有先前的有效命令。 (跳过无效的,所以如果以前错了,它就不会突然工作。)当重置REPL时,它会重新加载类,所以新命令可以使用重新编译的类的内容(事实上,旧的命令也将使用那些重新编译的类。)
这不是一般解决方案,但是使用可重新计算状态扩展单个会话的有用快捷方式。
注意:这适用于裸Scala REPL。如果你从SBT或其他环境运行它,它可能会或可能不会工作,这取决于SBT或其他环境如何打包类 - 如果你不更新正在使用的实际类路径上的内容,当然它赢了'工作!
答案 1 :(得分:27)
类重新加载不是一个简单的问题。事实上,这是JVM非常困难的事情。你确实有几个选择:
不幸的是,这些都受到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
,然后导入。