我先从 Scala 中 def、val 和 var 之间的区别开始。
def - 为右侧内容定义一个不可变标签,惰性评估 - 按名称评估。
val - 为右侧内容定义一个不可变标签,急切/立即评估 - 按价值评估。
var - 定义一个可变变量,最初设置为评估的右侧内容。
示例,定义
scala> def something = 2 + 3 * 4
something: Int
scala> something // now it's evaluated, lazily upon usage
res30: Int = 14
例子,val
scala> val somethingelse = 2 + 3 * 5 // it's evaluated, eagerly upon definition
somethingelse: Int = 17
示例,变量
scala> var aVariable = 2 * 3
aVariable: Int = 6
scala> aVariable = 5
aVariable: Int = 5
根据上述,来自 def 和 val 的标签不能被重新分配,并且在任何尝试的情况下都会引发如下错误:
scala> something = 5 * 6
<console>:8: error: value something_= is not a member of object $iw
something = 5 * 6
^
当类定义如下:
scala> class Person(val name: String, var age: Int)
defined class Person
然后实例化为:
scala> def personA = new Person("Tim", 25)
personA: Person
一个不可变标签是为那个特定的 Person 实例(即“personA”)创建的。每当需要修改可变字段“年龄”时,这种尝试都会失败:
scala> personA.age = 44
personA.age: Int = 25
正如预期的那样,“年龄”是不可变标签的一部分。处理此问题的正确方法是使用可变变量,如下例所示:
scala> var personB = new Person("Matt", 36)
personB: Person = Person@59cd11fe
scala> personB.age = 44
personB.age: Int = 44 // value re-assigned, as expected
很明显,从可变变量引用(即“personB”)可以修改类可变字段“age”。
我仍然要强调,一切都源于上述差异,任何 Scala 程序员都必须清楚这一点。