scala 中的val 、 var 、def

来源:互联网 发布:隆多臂展体测数据 编辑:程序博客网 时间:2024/06/15 21:19

断断续续学习scala也有一段时间了,初期总对val 与var 的理解不太透彻,今天来做做总结。

一般都知道val 表示不可变,var表示可变,比如:

val s ="hello" s="world"//错误,不能对val重新赋值 var i=1 i=2//没有问题 

但是在碰到可变与不可变数据结构的时候,容易造成迷惑:

val numbers= ArrayBuffer(1,2,3)numbers+=5//successvar numbers=Set(1,2,3)numbers+=5//success

咋一看val不是不可变的吗,怎么能numbers+=5? 
val numbers指向了一个可变的数据结构 数组缓冲ArrayBuffer ,numbers是可以进行 
numbers+=5操作的, 这是因为所指的这个对象是有自己的状态的,比如这里的对象是ArrayBuffer类型,这个的对象的状态是可以改变的,但是你不能val numbers =ArrayBuffer(1,2) 了,被val声明的numbers只能指向这个对象,但是这个对象自身的状态是可以改变的(因为是类型是数组缓冲) 
再看下一个: 
Set是一个不可变对象,被声明为var的numbers指向,numbers+=的意义是什么呢?它返回一个新的对象Set(1,2,3,5) 原来的Set(1,2,3) 你无法改变,因为他是一个不可变的对象,这个新的Set再重新被指向了numbers. 要明白,可变对象数组缓冲的方法“+=”返回的是修改后的原来的集合,而不可变对象Set的“+=”返回的是一个新的集合。

为了证明对象自身是有状态的,再看一下StackOverFlow上面的例子:

class A(n: Int) {  var value = n}class B(n: Int) {  val value = new A(n)}object Test {  def main(args: Array[String]) {    val x = new B(5)    x = new B(6) // Doesn't work, because I can't replace the object created on the line above with this new one.    x.value = new A(6) // Doesn't work, because I can't replace the object assigned to B.value for a new one.    x.value.value = 6 // Works, because A.value can receive a new object.  }}
可以看到 x 与x.value都不能被重新赋值,以为他们都被val声明,一旦指向一个对象就不能再被指向其他的对象了, 但是这个对象自身的状态是会改变的,例如x.value.value就能被重新赋值了。


  • val定义值时,会做call-by-value操作,
  • def则会做call-by-name操作。
  • 使用 def 每次都会重新进行取值。

    那么对应上面的情况,如果文件内容改变,由于方法体在被调用时会重新执行,将得到被修改后文件的内容。


 // 这是一个死循环 def loop: Boolean = loop // 用val定义时会做call-by-value,以下语句会block住 val x = loop  // 用def定义时,是做的call-by-name。故以下语句暂时不会执行,在用到y的时候才做evaluation def y = loop














 
原创粉丝点击