3

REPLでスコーピングがどのように機能するかを理解しようとしています。Joshua Suerethの本Scalaのセクション5.1.1を詳しく調べてみました。これは、Windows XP、Java 7、およびScala2.9.1にあります。DinnerREPLでクラスを宣言します。バインディングDinnerはローカルスコープに存在します。次に、ローカルにバインドされているため、インスタンス化します。

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

ここまでは順調ですね。名前Dinnerはローカルにバインドされており val x、への参照を保持できるを構築することもできますnew Dinner

私がこれまでに知っていることから、REPLは上記のコードをオブジェクトに内部的にラップします。さて、Scalaについての私の知識はまだそれほど深くはなく、ClassがREPLによって内部的にどのようにラップされるかを理解しようとしています。

これらのオブジェクトを評価するのに役立つREPLコマンドはありますか?

4

1 に答える 1

3

ここでは、REPL で何が起こっているかについて、非常に手早く汚い方法で説明します。

scala -Xprint:typer で REPL を呼び出す

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

上記で確認できるようにDinner、最終的には にラップされ$line1.$read.$iw.$iwます。次に何が起こるか見てみましょう。

[[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
  }
}

基本的には前と同じですが、$line2代わりに$line1. import $line1.$read.$iw.$iw.Dinnerの直前に注目してください$line2.$read.$iw.$iw

このようにして、コンパニオン オブジェクトを 2 つの異なる行で定義するとうまくいかない理由がわかります。それらは最終的に別のオブジェクトにラップされ、コンパニオンを同じスコープ/ソース ファイルで定義する必要があります。

于 2012-07-19T00:24:07.370 に答える