What are the internal implementation of var and val in Scala? interested in knowing the details of their implementations- what makes var a "var" how mutable structure is implemented vs val (more final like) structure which makes it immutable.
I'll answer by example, using scalac
and javap
.
First I create Test.scala
:
class Test {
val x = 1
var y = 2
}
Compile it via scalac Test.scala
to generate Test.class
, then use javap -p Test.class
to get
public class Test {
private final int x;
private int y;
public int x();
public int y();
public void y_$eq(int);
public Test();
}
So you can see that val x
became a private final
field on the class, and also a public final
method to return that value.
var y
became a non-final private field, and a getter+setter pair. The y_$eq(int)
is the setter. In scala, that would be def y_=(newY: Int): Unit
. Scala's syntax sugar will translate y = someValue
into a call to y_=(someValue)
.
You have to distinguish declarations (in a class template) from definitions (in a block, or in a template where they declare members and also form the constructor body)
A var
decl is specified in section 4.2 to be equivalent to a getter/setter pair.
As an implementation detail, a val
is just a getter.
Both members have a private backing field with a slightly mangled name: it has a trailing space.
There are a couple of anomalies, such as:
scala> class X { final val x = 7 } // the underlying field is not initialized
defined class X
scala> :javap -prv X
{
[snip]
private final int x;
flags: ACC_PRIVATE, ACC_FINAL
[snip]
public $line5.$read$$iw$$iw$X();
flags: ACC_PUBLIC
Code:
stack=1, locals=1, args_size=1
0: aload_0
1: invokespecial #14 // Method java/lang/Object."<init>":()V
4: return
Material difference between template and block:
scala> class Y { def y = { var z = 0; def z_=(zz: Int): Unit = ???; z = 1; z } }
scala> class Y { var z = 0; def z_=(zz: Int): Unit = ???; z = 1 }
<console>:7: error: method z_= is defined twice
In the REPL, you are really making templates (because everything is wrapped in a class):
scala> var z = 0 ; def z_=(zz: Int): Unit = ???
<console>:7: error: method z_= is defined twice
conflicting symbols both originated in file '<console>'
var z = 0 ; def z_=(zz: Int): Unit = ???
^
scala> { var z = 0 ; def z_=(zz: Int): Unit = ??? }
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