5

Assume this Java code:

public class A {
   public A(String g) {
      x += g.length();
   }

   private int x = 0;
}

If I create an instance of A, like this:

A a = new A("geo");

after this call, the value of x will be 3. What am I doing wrong in my Scala code?

class A(val g:String) {
  x += g.length
  var x:Int = 0
}

object x extends Application {
  val x = new A("geo")
  println(x.x)
}

This prints 0. I assumed that when the compiler reaches the var x:Int = 0, the body of the main constructor has ended. Am I wrong? How else could you declare instance variables in Scala ( assuming I don't want them in my constructor ) ?

1
  • 1
    Every line of code that is not inside a def (method body) is constructor code. Val and var initialization code is included in that and the constructor is the top-to-bottom accumulation of all that code. Note that this includes things like method calls interspersed between val, var and def definitions. Commented Dec 16, 2009 at 21:37

5 Answers 5

7

Keep in mind that your code translates into something similar (but not exactly) to this:

public class A {

  private final String g;
  private int x;

  public A(String g) {
    this.g = g;
    x_$eq(x() + g.length());
    x = 0;
  }

  public void x_$eq(int arg0) {
    x = arg0;
  }

  public int x() {
    return x;
  }

  public String g() {
    return g;
  }
}

But vars defined in (non-constructor) methods get translated into actual local variables.

Not sure if this explains the reasoning so much as highlights one of the differences.


EDIT - Changed "translation" from scala to java for clarity and ability to more accurately represent what is happening.

Sign up to request clarification or add additional context in comments.

3 Comments

So, why wasn't _x 3? That's how I'm reading the code representation.
But how is x treated? As a local variable? Is the compiler declaring it?
The var x is in instance variable in all cases. With the declaration var x: Int = 0, the variable x is a private variable with public x() and x_=() methods automatically created.
7

Your confusion results from a misunderstanding of how constructors in Scala works. Specifically, let's translate the Scala code you posted into Java:

class A(val g:String) {
  x += g.length
  var x:Int = 0
}

becomes

public class A {
   public A(String g) {
      x += g.length();
      x = 0;
   }
   private int x;
}

The reason is simple. The whole body of a class in Scala is the primary constructor for that class. That means the statements in it, and initializing val and var are statements, will be executed in the order they are found.

PS: Here is the actual, true rendition of that code.

Scala 2.7

C:\Users\Daniel\Documents\Scala\Programas> scalac -print A.scala
[[syntax trees at end of cleanup]]// Scala source: A.scala
package <empty> {
  class A extends java.lang.Object with ScalaObject {
    @remote def $tag(): Int = scala.ScalaObject$class.$tag(A.this);
    <paramaccessor> private[this] val g: java.lang.String = _;
    <stable> <accessor> <paramaccessor> def g(): java.lang.String = A.this.g;
    private[this] var x: Int = _;
    <accessor> def x(): Int = A.this.x;
    <accessor> def x_=(x$1: Int): Unit = A.this.x = x$1;
    def this(g: java.lang.String): A = {
      A.this.g = g;
      A.super.this();
      A.this.x_=(A.this.x().+(g.length()));
      A.this.x = 0;
      ()
    }
  }
}

Scala 2.8

C:\Users\Daniel\Documents\Scala\Programas>scalac -print A.scala
[[syntax trees at end of cleanup]]// Scala source: A.scala
package <empty> {
  class A extends java.lang.Object with ScalaObject {
    <paramaccessor> private[this] val g: java.lang.String = _;
    <stable> <accessor> <paramaccessor> def g(): java.lang.String = A.this.g;
    private[this] var x: Int = _;
    <accessor> def x(): Int = A.this.x;
    <accessor> def x_=(x$1: Int): Unit = A.this.x = x$1;
    def this(g: java.lang.String): A = {
      A.this.g = g;
      A.super.this();
      A.this.x_=(A.this.x().+(g.length()));
      A.this.x = 0;
      ()
    }
  }
}

3 Comments

Good to see you have as much difficulty as me free-handing java without slipping in scala-isms. You missed a semi-colon and used the non-existent-in-java underscore initializer.
Ok, code fixed, and compiled to make sure. Why can't Java be reasonable? :-)
Ok, I fixed the code, though I see you offered a superior answer (ie, a more accurate translation into Java).
4

Change this:

class A(val g:String) {
  x += g.length
  var x:Int = 0
}

to

class A(val g:String) {
  var x = g.length

}

1 Comment

Why not just make it a val? There's no evidence from the sample code that it needs to be modified.
4

var x:Int = 0 make this the first line of the constructor

class A(val g:String) {  
   var x:Int = 0  
   x += g.length  
}

Comments

0

Why does Scala let you reference x before you declared it? In any other scope, this would be illegal.

scala> def foo(g:String) = { x+=1; var x=0; x}
<console>:4: error: forward reference extends over definition of variable x
       def foo(g:String) = { x+=1; var x=0; x}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.