用于演示嵌套作用域的Scala代码在Java中的行为有所不同

时间:2012-07-23 20:12:05

标签: java scala

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

在Scala Sheltie类的主体中,在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)
}

3 个答案:

答案 0 :(得分:6)

当你说Scala 允许在类体中调用时,正文实际上是构造函数,所以这相当于:

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

在Java中。

答案 1 :(得分:5)

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

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

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

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

答案 2 :(得分:2)

只是补充约barkNum。 Scala有关于作用域和声明的简单规则。简言之:

  • 在顶层,只允许使用类,特征,对象和包对象。
    • 这是JVM强加的限制。
  • 任何块({} - 定界代码)都接受任何类型的声明。
    • 包括课程,特征和对象的主体。
  • 内部声明影响外部声明。