Val 和Var 的区别
一、最直观的就是:val定义的变量不能被再次赋值,而var定义的可以,见下图
scala> val s=10
s: Int = 10
scala> s=11
<console>:27: error: reassignment to val
s=11
^
scala> var a=10
a: Int = 10
scala> a=11
a: Int = 11
二、事实上,var 修饰的对象引用可以改变,val 修饰的则不可改变,但对象的状态却是可以改变的。
class A(n: Int) {
var value = n //利用可变修饰符定义一个值
}
class B(n: Int) {
val value = new A(n) //利用不变修饰符定义一个值
}
class C(n: Int) {
var value = new A(n) //利用可变修饰符定义一个值
}
object Test {
def main(args: Array[String]) {
val x = new B(5) //首先定义一个不可变变量x,所以下一行会报错
x = new B(6) // 错误,因为 x 为 val 修饰的,引用不可改变
x.value = new A(6) // 错误,因为 x.value 为 val 修饰的,引用不可改变
val y = new C(5) //定义一个不可变变量y,但是y.value是 var修饰的,所以下一行正确
y.value = new A(7) //因为y.value 是var修饰的。当然y = new C(7)依然报错,因为y是val修饰的
x.value.value = 6 // 正确,x.value.value 为var 修饰的,可以重新赋值
}
}
仔细看上面的备注解释,就可以明白var和val的区别了;
针对变量的不变性,使用val的好处:
一是,如果一个对象不想改变其内部的状态,那么由于不变性,我们不用担心程序的其他部分会改变对象的状态;
二是,当用 var 修饰的时候,你可能在多个地方重用 var 修饰的变量,这样会产生下面的问题:
- 对于阅读代码的人来说,在代码的确定部分中知道变量的值是比较困难的;
- 你可能会在使用代码前初始化代码,这样会导致错误;
针对变量的可变性,使用var的好处:
- 使用可变性可以大幅度提高程序的执行效率。
- 避免了由于其他用途而对变量进行重用
三、def需要注意的地方
abstract class Person {
def id: Int
}
class Student extends Person{
override var id = 9527 //Error: method id_= overrides nothing
}
上述继承时,发生错误,因为用def定义的成员变量,不具备setter和getter方法。
那么如果父类中只定义了一个方法def id: Int
,用来生成用户的id,而子类用var变量重写这个方法的话override var id = 9527
,编译会报错method id_=overrides nothing
,从报错中可以看出来,由于scala会为var变量自动生成了一个setter方法(id_),但是父类并没有这个方法,所以是无法重写的。
如果改下,必须为以下代码,此时重新定义了父类的setter方法
abstract class Person {
def id: Int
def id_=(value: Int) //父类必须有set方法
}
class Student extends Person{
override var id = 9527 //为var变量自动生成get和set方法
}
也可以利用var定义函数的成员变量
abstract class Person1 {
var id: Int
}
class Student extends Person1{
var id = 9527 //为var变量自动生成get和set方法
}
这样就可以直接使用了,不会出错了。