我在Scala REPL中运行简单代码,创建两个具有单Int
值x
的类。以下是:
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
我的理解是,对于类C
,变量x
将成为可变变量(默认为var
),而对于类D则变为不可变变量。但是,我遇到过x
不是C
成员的问题。
怎么样?
答案 0 :(得分:3)
要研究这个问题,我们可以进行逆向工程,看看“编译器会做什么?” :)
为此,我们正在使用内容编译类C.scala
class C(x: Int){}
运行:
scalac C.scala
这样,生成C.class
。
现在,我们可以使用java class disassembler javap来查看编译器将生成什么。
运行
javap -p C.class
会产生:
public class C {
public C(int);
}
如果我们重复整个程序
class D(val x: Int){}
我们会屈服:
public class D {
private final int x;
public int x();
public D(int);
}
我们可以看到区别在于关键字val
告诉类创建一个getter方法。
回到你的假设,没有val
关键字,类变量将被定义为可变:这是错误的。为了证明我们可以更深入地进行拆解。通过运行:
javap -p -v C.class
我们得到(在很多其他信息中)这个片段:
{
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
}
你可以清楚地看到类变量x
仍然被声明为final
,因此是不可变的。
答案 1 :(得分:1)
Scala类中的属性可以具有以下修饰符:
val
使属性不可变;它总是公开的 - 这是有道理的,因为价值无法改变var
使属性变为可变且公开代码示例:
// 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)
有关构造函数和类的更多信息:http://joelabrahamsson.com/learning-scala-part-four-classes-and-constructors/