Frage

Ich habe fast immer eine oder zwei Scala REPL-Sitzungen geöffnet, was es sehr einfach macht, Java- oder Scala-Klassen schnell zu testen.Aber wenn ich eine Klasse ändere und sie neu kompiliere, fährt die REPL mit der geladenen alten fort.Gibt es eine Möglichkeit, die Klasse neu zu laden, anstatt die REPL neu starten zu müssen?

Um ein konkretes Beispiel zu geben: Angenommen, wir haben die Datei Test.scala:

object Test { def hello = "Hello World" }

Wir kompilieren es und starten die 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

Dann ändern wir die Quelldatei in

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

aber wir können es nicht verwenden:

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;
War es hilfreich?

Lösung

Das Nachladen der Klasse ist kein einfaches Problem. Tatsächlich macht es das JVM sehr schwierig. Sie haben jedoch ein paar Optionen:

  • Starten Sie die Scala Repl im Debug -Modus. Der JVM-Debugger verfügt über ein integriertes Nachladen, das auf der Methodenebene funktioniert. Es wird Ihnen bei dem von Ihnen angegebenen Fall nicht helfen, aber es würde etwas Einfaches wie die Änderung einer Methodenimplementierung behandeln.
  • Verwenden Sie Jrebel (http://www.zeroturnaround.com/jrebel). Jrebel ist im Grunde genommen eine übergeladene Klassen-Nachladenlösung für das JVM. Es kann Mitglied Addition/Entfernung, neue/entfernte Klassen, Definitionsänderungen usw. verarbeiten kippen Handle ist Änderungen in der Klassenhierarchie (z. B. Hinzufügen einer Super-Schnittstelle). Es ist kein kostenloses Tool, aber sie bieten eine ergänzende Lizenz, die sich auf Scala Compilation -Einheiten beschränkt.

Leider sind beide durch die Implementierungsdetails der Scala Reples begrenzt. Ich benutze Jrebel, und es macht normalerweise den Trick, aber es gibt immer noch Fälle, in denen die Repl nicht die Reloaded -Klasse (ES) widerspiegelt. Trotzdem ist es besser als nichts.

Andere Tipps

Es gibt eine Alternative zum Nachladen der Klasse, wenn das Ziel nicht frühere Befehle wiederholen muss. Die Reply hat den Befehl

:replay

Dadurch wird die Repl -Umgebung neu gestartet und alle vorherigen gültigen Befehle zurückgegeben. (Die Ungültigen werden übersprungen. Wenn es also vorher falsch war, funktioniert es nicht plötzlich.) Wenn die Reples zurückgesetzt wird, laden Sie Klassen neu, sodass neue Befehle den Inhalt neuer Klassen verwenden können (tatsächlich die alten Befehle wird auch diese neu kompilierten Klassen verwenden).

Dies ist keine allgemeine Lösung, sondern eine nützliche Abkürzung, um eine individuelle Sitzung mit einem erneuten Zustand zu erweitern.

Hinweis: Dies gilt für die bare Scala Repl. Wenn Sie es aus SBT oder einer anderen Umgebung ausführen, kann dies abhängig von der Art und Weise, wie SBT oder die anderen Umgebungsklassen paket, oder nicht, wenn Sie nicht aktualisieren, was sich auf dem tatsächlichen Klassenpfad befindet, natürlich gewonnen hat. Ich arbeite!

Es gibt einen Befehl, der Sie erfolgt

:load path/to/file.scala

Dies lädt die Scala -Quelldatei neu und wird in Klassen neu kompiliert. Dann können Sie Ihren Code wiederholen

Das funktioniert bei mir....

Wenn Ihre neue Quelldatei Test.scala sieht ungefähr so ​​aus...

package com.tests

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

Sie müssen die neuen Änderungen zunächst in die Scala-Konsole (REPL) laden.

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

Importieren Sie dann das Paket erneut, damit Sie in der Scala-Konsole auf den neuen Code verweisen können.

import com.tests.Test

Genießen Sie jetzt Ihren neuen Code, ohne Ihre Sitzung neu zu starten :)

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

Wenn sich die .scala -Datei im Verzeichnis befindet, in dem Sie mit der Replin beginnen, können Sie den vollständigen Pfad begeben, einfach setzen :load myfile.scala, und dann importieren.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top