I am trying to understand how scoping works in the REPL. I tried following Section 5.1.1 of Joshua Suereth's book Scala in depth.This is on Windows XP, Java 7 and Scala 2.9.1. I declare a class Dinner
in the REPL. The binding Dinner
exists in the local scope. Then I instantiate because it is locally bound.
scala> class Dinner {
| val veggie="broccoli"
| def announceDinner(veggie: String){
| println("Dinner happens to be tasteless " + veggie + " soup")
| }
| }
defined class Dinner
scala> new Dinner
res1: Dinner = Dinner@27fb77
So far so good. The name Dinner
was bound locally and we could also construct a val x
that could hold a reference to new Dinner
.
From what I know so far, The REPL will wrap the above code in objects internally. Okay, my knowledge of Scala is not quite as deep yet and I am trying to understand how Class might be internally wrapped by the REPL.
Is there an REPL command that can help me evaluate these objects?
Here goes a very quick and dirty way to what is going on in the REPL.
Invoke the REPL with scala -Xprint:typer
scala> class Dinner {
| val veggie="broccoli"
| def announceDinner(veggie: String){
| println("Dinner happens to be tasteless " + veggie + " soup")
| }
| }
[[syntax trees at end of typer]]// Scala source: <console>
package $line1 {
final object $read extends java.lang.Object with ScalaObject {
def this(): object $line1.$read = {
$read.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line1.$read.$iw = {
$iw.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line1.$read.$iw.$iw = {
$iw.super.this();
()
};
class Dinner extends java.lang.Object with ScalaObject {
def this(): $line1.$read.$iw.$iw.Dinner = {
Dinner.super.this();
()
};
private[this] val veggie: java.lang.String = "broccoli";
<stable> <accessor> def veggie: java.lang.String = Dinner.this.veggie;
def announceDinner(veggie: String): Unit = scala.this.Predef.println("Dinner happens to be tasteless ".+(veggie).+(" soup"))
}
}
}
}
}
[[syntax trees at end of typer]]// Scala source: <console>
package $line1 {
final object $eval extends java.lang.Object with ScalaObject {
def this(): object $line1.$eval = {
$eval.super.this();
()
};
private[this] val $print: String = {
$read.$iw.$iw;
"defined class Dinner\012"
};
<stable> <accessor> def $print: String = $eval.this.$print
}
}
defined class Dinner
As you can check above Dinner
ends up wrapped into $line1.$read.$iw.$iw
. Now let's see what happens next:
[[syntax trees at end of typer]]// Scala source: <console>
package $line2 {
final object $read extends java.lang.Object with ScalaObject {
def this(): object $line2.$read = {
$read.super.this();
()
};
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line2.$read.$iw = {
$iw.super.this();
()
};
import $line1.$read.$iw.$iw.Dinner;
final object $iw extends java.lang.Object with ScalaObject {
def this(): object $line2.$read.$iw.$iw = {
$iw.super.this();
()
};
private[this] val res0: $line1.$read.$iw.$iw.Dinner = new $line1.$read.$iw.$iw.Dinner();
<stable> <accessor> def res0: $line1.$read.$iw.$iw.Dinner = $iw.this.res0
}
}
}
}
[[syntax trees at end of typer]]// Scala source: <console>
package $line2 {
final object $eval extends java.lang.Object with ScalaObject {
def this(): object $line2.$eval = {
$eval.super.this();
()
};
lazy private[this] var $result: $line1.$read.$iw.$iw.Dinner = {
$eval.this.$print;
$line2.$read.$iw.$iw.res0
};
private[this] val $print: String = {
$read.$iw.$iw;
"res0: $line1.$read.$iw.$iw.Dinner = ".+(scala.runtime.ScalaRunTime.replStringOf($line2.$read.$iw.$iw.res0, 1000))
};
<stable> <accessor> def $print: String = $eval.this.$print
}
}
Basically the same thing as before but using $line2
instead of $line1
. Notice the import $line1.$read.$iw.$iw.Dinner
right before $line2.$read.$iw.$iw
.
This way we can see why defining companion objects in two different lines doesn't work, they end up wrapped into different objects and companions need to be defined in the same scope/source file.
来源:https://stackoverflow.com/questions/11549174/trying-to-understand-how-classes-declared-on-the-repl-are-treated-internally