我编写了一个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)
}
答案 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有关于作用域和声明的简单规则。简言之: