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 ) ?
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.
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;
()
}
}
}
Change this:
class A(val g:String) {
x += g.length
var x:Int = 0
}
to
class A(val g:String) {
var x = g.length
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With