Reputation: 25028
I am running simple code in Scala REPL that creates two classes with a single Int
value x
. Here's how:
scala> class C(x: Int){}
defined class C
scala> new C(100).x
<console>:13: error: value x is not a member of C
new C(100).x
^
scala> class D(val x: Int){}
defined class D
scala> new D(100).x
res1: Int = 100
My understanding was that for class C
the variable x
would become a mutable variable (var
by default) and for class D an immutable variable. However, I have run into this issue where x
isn't a member of C
.
How so?
Upvotes: 1
Views: 78
Reputation: 1131
To research this question we can reverse engineer to see "what would the compiler do?" :)
For that, we are compiling the class C.scala
with the content
class C(x: Int){}
by running:
scalac C.scala
this, generates C.class
.
Now, we can use the java class disassembler javap to see what the compiler would generate.
running
javap -p C.class
would produce:
public class C {
public C(int);
}
if we are repeating the whole procedure with
class D(val x: Int){}
we would yield:
public class D {
private final int x;
public int x();
public D(int);
}
We can see that the difference is that the keyword val
is telling the class to create a getter method.
Coming back to your assumption that without the val
keyword the class variable would be defined as mutable: this is wrong. To prove that we can go one level deeper into the disassembling. By running:
javap -p -v C.class
we get (among a lot of other information) this snippet :
{
public C(int);
descriptor: (I)V
flags: ACC_PUBLIC
Code:
stack=1, locals=2, args_size=2
0: aload_0
1: invokespecial #14 // Method java/lang/Object."<init>":()V
4: return
LocalVariableTable:
Start Length Slot Name Signature
0 5 0 this LC;
0 5 1 x I
LineNumberTable:
line 4: 0
line 2: 4
MethodParameters:
Name Flags
x final
}
you can clearly see that the class variable x
is still declared as final
and thus, immutable.
Upvotes: 3
Reputation: 693
Attributes in Scala classes can have the following modifiers:
val
makes the attribute immutable; it's always public - this makes sense since the value can't be changedvar
makes the attribute mutable and publicCode examples:
// no modifier
class A(x: Int) {
def print() = {
x += 1 // this i fine, it's mutable
println(x)
}
}
val a = new A(3)
// a.x - compile error, it's private
// var
class A(var x: Int) {
def print() = {
x += 1 // this is fine, it's mutable
println(x)
}
}
val a = new A(3)
a.x // you can do this since it's public (modifier var)
// val
class A(val x: Int) {
def print() = {
// x += 1 // can't do this, it's immutable
println(x)
}
}
val a = new A(3)
a.x // you can do this since it's public (modifier val)
More about constructors and classes: http://joelabrahamsson.com/learning-scala-part-four-classes-and-constructors/
Upvotes: 1