试图了解如何在内部处理 REPL 上声明的类 [英] Trying to understand how classes declared on the REPL are treated internally

查看:57
本文介绍了试图了解如何在内部处理 REPL 上声明的类的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图了解 REPL 中的作用域是如何工作的.我尝试深入学习 Joshua Suereth 的书 Scala 的第 5.1.1 节.这是在 Windows XP、Java 7 和 Scala 2.9.1 上.我在 REPL 中声明了一个 Dinner 类.绑定 Dinner 存在于本地范围内.然后我实例化,因为它是本地绑定的.

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

到目前为止一切顺利.名称 Dinner 在本地绑定,我们还可以构造一个 val x 来保存对 new Dinner 的引用.

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.

据我目前所知,REPL 将在内部将上述代码包装在对象中.好吧,我对 Scala 的了解还不够深入,我正在尝试了解 REPL 如何在内部封装 Class.

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.

是否有 REPL 命令可以帮助我评估这些对象?

Is there an REPL command that can help me evaluate these objects?

推荐答案

这里有一个非常快速和肮脏的方式来了解 REPL 中发生的事情.

Here goes a very quick and dirty way to what is going on in the REPL.

使用 scala -Xprint:typer 调用 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

正如你在上面看到的,Dinner 最终被包裹在 $line1.$read.$iw.$iw 中.现在让我们看看接下来会发生什么:

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

与之前基本相同,但使用 $line2 而不是 $line1.请注意 $line2.$read.$iw.$iw 之前的 import $line1.$read.$iw.$iw.Dinner.

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.

这篇关于试图了解如何在内部处理 REPL 上声明的类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆