1

我编写了一个 Scala 类Sheltie来了解作用域在 Scala 中是如何工作的。我编写了一个等效的 Java Sheltie 类作为交叉引用。这就是我遇到麻烦的地方。

在 ScalaSheltie类的主体中,有一个对被调用方法的方法调用bark,以及在调用println之后的语句bark。等效的方法调用bark()可以放在另一个方法内部的等效 Java 类中,但在任何方法之外,它可以理解地抱怨Duplicate method bark().

我了解 Java 代码的工作原理,所以这种行为(在 Java 中)并不奇怪。令人困惑的是 Scala 的行为方式为何如此。

我希望解决的是:为什么 Scala 允许在类主体中“调用”以及为什么它允许在 if 块中创建另一个 val 定义,而 Java 不允许。

Foo.scala

class Sheltie {
  val barkNum = 10

  def bark() {
    //local barkNum of "bark" method
    val barkNum = 20

     if(true){
       //local "barkNum" of if-block
       val barkNum = 30 //why does Scala not complain of a duplicate local variable, when            Java does in the equivalent program Sheltie.java
       println("Inside if block: No of times Riley barked is " + barkNum)
     }

     println("Outside if block: No of times Riley barked is " + barkNum)
  }

  bark //Why does this work, when you can't do this in Java
  println("Outside bark: No of times Riley barked is " + barkNum)
}
4

3 回答 3

6

当您说 Scala允许在类主体中调用时,主体实际上是构造函数,因此这相当于具有:

public Sheltie()
{
    bark();
    System.out.println("Outside bark: No of times Riley barked is " + barkNum);
}

在爪哇。

于 2012-07-23T20:24:22.930 回答
5

在 Scala 中,“类主体”中的语句(不包括声明)作为默认构造函数的一部分执行。当您实例化一个 class 对象时,您将能够观察到这一点Sheltie。额外的构造函数在 Scala中称为辅助构造函数。

class Test(a: Int) {
  println("a = " + a)
}

new Test(1) /* Prints a = 1 */

关于可变阴影,实际上没有正确或错误的事情要做。Scala 允许您隐藏变量,而其他语言则不允许。我的猜测是它是允许的,因为以函数式编程通常会导致大量局部变量存在于非常有限的范围内,例如,来自闭包声明。

于 2012-07-23T20:20:25.343 回答
2

只是补充一下barkNum。Scala 有关于范围和声明的简单规则。简要地:

  • 在顶层,只允许使用类、特征、对象和包对象。
    • 这是 JVM 强加的限制。
  • 任何块({} 分隔的代码)都接受任何类型的声明。
    • 这包括类、特征和对象的主体。
  • 内部声明遮蔽外部声明。
于 2012-07-24T13:07:37.790 回答