scala val 与var 区别

本文探讨了Scala中val与var的区别,val定义的对象不可更改,而var定义的对象可以更改。文章通过实例对比了两者在代码安全性、可读性和性能上的差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一个var和VAL定义在Scala之间的区别是什么?


一之间的区别是什么varval在Scala中定义和为什么的语言都需要?为什么你会选择val在一个var反之亦然?

1. 正如许multiplayer所说,该对象分配给一个val不能被替换,并且该对象分配给一个var可以。然而,该对象可以有其内部状态改变。例如:
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,我们可以改变对象的状态。在它的根,然而 CodeGo.net,有一个var。 现在,是不可改变的原因有很多好东西。首先,如果一个对象不改变内部状态,你不必担心,如果你的代码的其他部分改变它。例如:
x = new B(0)
f(x)
if (x.value.value == 0)
 println("f didn't do anything to x")
else
 println("f did something to x")
这与多线程系统尤为重要。在多线程系统中,会出现以下情况:
x = new B(1)
f(x)
if (x.value.value == 1) {
 print(x.value.value) // Can be different than 1!
}
如果val和不可变的数据结构(即,避免数组,一切都在scala.collection.mutable等),你可以放心不会出现这种情况。也就是说,除非有代码,甚至一做反思技巧-反射可以改变“一成不变”的价值观,很遗憾。 这是原因之一,但还有另外一个原因吧。何时var,你可以引诱到var用于多种用途。这有问题: 这将是更困难的人阅读代码知道什么是可变的代码中的某一部分的值。 您可能忘记重新初始化代码路径变量,并最终在代码下游传递错误的价值观。 简单地说,使用val更安全,并导致更易读的代码。 我们可以的话,去了另一个方向。如果val是更好的,为什么var呢?那么,语言没有采取这条路线,但也有在哪些情况下可变性提高性能,很多。 例如,考虑一个不可变的Queue。当你要么enqueuedequeue在它的东西,你得到一个新的Queue对象。怎么样的话,你会去处理它的所有项目? 我会去通过一个例子。比方说,你有数字的队列,你想了许多了出来。举例来说,如果我有一个队列,2,1,3,按照这个顺序,我想拿回数213。让我们先解决它与mutable.Queue
def toNum(q: scala.collection.mutable.Queue[Int]) = {
 var num = 0
 while (!q.isEmpty) {
 num *= 10
 num += q.dequeue
 }
 num
}
此代码是快速和容易理解。它的主要缺点是,所传递的队列由modifiedtoNum,所以你必须做出一个副本事前。这就是一种对象的immutability是你通过free的。 现在,让我们隐蔽它的immutable.Queue
def toNum(q: scala.collection.immutable.Queue[Int]) = {
 def recurse(qr: scala.collection.immutable.Queue[Int], num: Int): Int = {
 if (qr.isEmpty)
  num
 else {
  val (digit, newQ) = qr.dequeue
  recurse(newQ, num * 10 + digit)
 }
 }
 recurse(q, 0)
}
我不变量来轨迹我num,就像在这个例子中,我需要求助于递归。在这种情况下,它是一个尾递归,其中有相当不错的表现。但事实并非总是如此:他们就是没有好(可读,简单)尾递归的解决方案。 但是,请注意,我可以重写这些代码的immutable.Queuevar在例如:
def toNum(q: scala.collection.immutable.Queue[Int]) = {
 var qr = q
 var num = 0
 while (!qr.isEmpty) {
 val (digit, newQ) = qr.dequeue
 num *= 10
 num += digit
 qr = newQ
 }
 num
}
此代码仍然是有效的,不需要递归,你不必担心你是否有让你的队列与否的一个副本之前调用toNum。当然,我避免用于其他用途的变量,而这个函数之外没有代码能够看到他们,所以我并不需要担心他们的价值观改变从一行到下一个-除非我明确地这样做。 Scala的选择,让这样做,如果它是最好的解决方案。其他语言的选择做出这样的代码很难。价格scala(和广泛的可变性的任何语言)支付是不拥有尽可能多的回旋余地在优化代码,因为它可能并非如此。 Java的答案是优化的基础上运行配置文件的代码。我们会继续和有关利弊两侧。 就个人而言,我认为Scala的罢工适当的平衡,现在。它不是完美的,到目前为止。我认为无论是Clojure和Haskell中没有采纳scala非常有趣的概念,但Scala有其自身的优势,以及。我们将看到了未来。 
2. val在决赛中,也就是说,不能设置。想final在java中。 
3. 不同的是,一个var可以被重新分配给一个而val不能。的可变性,或其他任何实际分配,是一个次要的问题:
import collection.immutable
import collection.mutable
var m = immutable.Set("London", "Paris")
m = immutable.Set("New York") //Reassignment - I have change the "value" at m.
鉴于:
val n = immutable.Set("London", "Paris")
n = immutable.Set("New York") //Will not compile as n is a val.
因此:
val n = mutable.Set("London", "Paris")
n = mutable.Set("New York") //Will not compile, even though the type of n is mutable.
如果你正在建设一个数据结构,它的所有字段都vals,则该数据结构是不变的,因此,它的状态不能改变。 
4. val表示不可变的,var指可变的。 满 
5. “不变的,可变的。” 意译,“价值与变量”。 出现这种情况是重要的(这两个概念的定义是什么程序是所有的本质),以及面向对象已经成功在面向对象的blur区分,唯一的公理是:“一切都是对象”。并且,作为一个结果,大量的这些日子往往不理解/欣赏/承认,他们已经被洗脑成“思想的面向对象的方式”往往导致可变/可变对象一样无处不在,当值/不可变的对象可能/经常有好些。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值