ilango
ilango

Reputation: 1287

Scala code to demonstrate nested scopes behaves differently in Java

I have written a Scala class Sheltie to understand how scopes work in Scala. I wrote an equivalent Java Sheltie class just as a cross-reference. This is where I ran into trouble.

In the body of the Scala Sheltie class, there is a method call to the method called bark and a println statement just after the bark call. An equivalent method call bark() can be placed in the equivalent Java class inside another method, but outside of any method, it understandably complains of Duplicate method bark().

I understand how Java code works, so this behavior (in Java) is not surprising. What perplexes is why Scala behaves the way it does.

What I hope to solve is: Why does Scala allow "calls" in the class body and why it allows one to create another val definition in the if block, when Java does not.

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

Upvotes: 1

Views: 188

Answers (3)

Reimeus
Reimeus

Reputation: 159754

When you say Scala allows calls in the class body, the body is actually the constructor, so this is equivalent to having:

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

in Java.

Upvotes: 6

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297175

Just complementing about barkNum. Scala has simple rules about scoping and declarations. Briefly:

  • At the top level, only classes, traits, objects and package objects are allowed.
    • This is a JVM-imposed restriction.
  • Any block ({}-delimited code) accepts any kind of declaration.
    • That includes the bodies of classes, traits and objects.
  • Inner declarations shadows outer declarations.

Upvotes: 2

Malte Schwerhoff
Malte Schwerhoff

Reputation: 12852

In Scala, statements (excluding declarations) "in the class body" are executed as part of the default constructor. You will be able to observe this when you instantiate an object of class Sheltie. Additional constructors are called auxiliary constructors in Scala.

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

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

Regarding variable shadowing, there isn't really a right or wrong thing to do. Scala allows you to shadow variables, other languages don't. My guess is that it is allowed because programming in a functional style often leads to lots of local variables existing in a very limited scope, e.g., from closure declarations.

Upvotes: 5

Related Questions