如何在 Scala REPL 中重新加载类或包?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2471947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to reload a class or package in Scala REPL?
提问by Rex Kerr
I almost always have a Scala REPL session or two open, which makes it very easy to give Java or Scala classes a quick test. But if I change a class and recompile it, the REPL continues with the old one loaded. Is there a way to get it to reload the class, rather than having to restart the REPL?
我几乎总是打开一两个 Scala REPL 会话,这使得对 Java 或 Scala 类进行快速测试变得非常容易。但是如果我更改一个类并重新编译它,REPL 会继续加载旧的类。有没有办法让它重新加载类,而不必重新启动 REPL?
Just to give a concrete example, suppose we have the file Test.scala:
举一个具体的例子,假设我们有文件 Test.scala:
object Test { def hello = "Hello World" }
We compile it and start the REPL:
我们编译它并启动 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
Then we change the source file to
然后我们把源文件改成
object Test {
def hello = "Hello World"
def goodbye = "Goodbye, Cruel World"
}
but we can't use it:
但我们不能使用它:
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;
采纳答案by Daniel Spiewak
Class reloading is not an easy problem. In fact, it's something that the JVM makes very difficult. You do have a couple options though:
类重载不是一个容易的问题。事实上,这是 JVM 非常困难的事情。不过,您确实有几个选择:
- Start the Scala REPL in debug mode. The JVM debugger has some built-in reloading which works on the method level. It won't help you with the case you gave, but it would handle something simple like changing a method implementation.
- Use JRebel (http://www.zeroturnaround.com/jrebel). JRebel is basically a super-charged class reloading solution for the JVM. It can handle member addition/removal, new/removed classes, definition changes, etc. Just about the only thing it can'thandle is changes in class hierarchy (adding a super-interface, for example). It's not a free tool, but they do offer a complementary license which is limited to Scala compilation units.
- 在调试模式下启动 Scala REPL。JVM 调试器具有一些在方法级别工作的内置重新加载。它不会帮助你解决你给出的案例,但它会处理一些简单的事情,比如改变方法实现。
- 使用 JRebel ( http://www.zeroturnaround.com/jrebel)。JRebel 基本上是 JVM 的超负荷类重新加载解决方案。它可以处理成员添加/删除、新/删除类、定义更改等。几乎唯一不能处理的是类层次结构的更改(例如,添加超级接口)。它不是免费工具,但它们确实提供了仅限于 Scala 编译单元的补充许可证。
Unfortunately, both of these are limited by the Scala REPL's implementation details. I use JRebel, and it usually does the trick, but there are still cases where the REPL will not reflect the reloaded class(es). Still, it's better than nothing.
不幸的是,这两者都受到 Scala REPL 实现细节的限制。我使用 JRebel,它通常可以解决问题,但仍然存在 REPL 不会反映重新加载的类的情况。不过,总比没有好。
回答by Rex Kerr
There is an alternative to reloading the class if the goal is to not have to repeat previous commands. The REPL has the command
如果目标是不必重复以前的命令,则可以选择重新加载类。REPL 有命令
:replay
which restarts the REPL environment and plays back all previous valid commands. (The invalid ones are skipped, so if it was wrong before, it won't suddenly work.) When the REPL is reset, it does reload classes, so new commands can use the contents of recompiled classes (in fact, the old commands will also use those recompiled classes).
这将重新启动 REPL 环境并播放所有以前的有效命令。(无效的被跳过,所以如果之前出错,它不会突然起作用。)REPL重置时,它会重新加载类,因此新命令可以使用重新编译的类的内容(实际上是旧命令也将使用那些重新编译的类)。
This is not a general solution, but is a useful shortcut to extend an individual session with re-computable state.
这不是通用的解决方案,而是使用可重新计算状态扩展单个会话的有用快捷方式。
Note: this applies to the bare Scala REPL. If you run it from SBT or some other environment, it may or may not work depending on how SBT or the other environment packages up classes--if you don't update what is on the actual classpath being used, of course it won't work!
注意:这适用于裸 Scala REPL。如果你从 SBT 或其他一些环境运行它,它可能会或可能不会工作,这取决于 SBT 或其他环境如何打包类——如果你不更新正在使用的实际类路径上的内容,当然它不会'工作!
回答by jiahut
There is an command meet you requirement
有一个命令满足你的要求
:load path/to/file.scala
which will reload the scala source file and recompiled to classes , then you can replay you code
这将重新加载 scala 源文件并重新编译为类,然后您可以重放代码
回答by cevaris
This works for me....
这对我有用....
If your new source file Test.scalalooks something like this...
如果您的新源文件Test.scala看起来像这样...
package com.tests
object Test {
def hello = "Hello World"
def goodbye = "Goodbye, Cruel World"
}
You first have to load the new changes into Scala console (REPL).
您首先必须将新更改加载到 Scala 控制台 (REPL) 中。
:load src/main/scala/com/tests/examples/Test.scala
Then re-import the package so you can reference the new code in Scala console.
然后重新导入包,以便您可以在 Scala 控制台中引用新代码。
import com.tests.Test
Now enjoy your new code without restarting your session :)
现在无需重新启动会话即可享受您的新代码:)
scala> Test.goodbye
res0: String = Goodbye, Cruel World
回答by Ignacio
If the .scala file is in the directory where you start the REPL you can ommit the full path, just put :load myfile.scala, and then import.
如果 .scala 文件在您启动 REPL 的目录中,您可以省略完整路径,只需放置:load myfile.scala,然后导入。

