2013-04-11 78 views
1

我以为我对Scala对引用类型(即来自AnyRef的引用类型)的处理有一个牢固的把握,但现在我不太确定。scala赋值与参考类型

如果我创建了一个简单的类像这样

class C(var x: Int = 0) {} 

,并定义了几个实例

var a = new C 
var b = new C(1) 
var c = new C(2) 

,然后我给你

a = b 

我没有得到一(浅)复制,而是对a实例的原始引用永远丢失,而a和b本质上是同一个对象的“别名”克拉。 (这可以通过查看这些项目的地址来看到)。这很好,很明智。同样清楚的是,这些是参考(与数值相对),因为我可以做

c = null 

并且这不会产生错误。

现在,假设我这样做

import scala.math.BigInt 
var x = BigInt("12345678987654321") 
var y = BigInt("98765432123456789") 
var z = x + y 

此创建三个BigInts,其中x,y和z,因为,我想,这些引用。事实上,我可以做

z = null 

并再次得到没有错误。然而,

y = x 
x += 1 

原因Y进行更改,即,似乎在这种情况下,分配并没有简单地创建另一个“名字”对象的简称由X,而是由它的一个副本。

为什么会发生这种情况?我无法找到任何机制(例如,类似于C++的“拷贝构造函数”),这些机制将被直观的引用赋值悄悄地调用(似乎是)。

任何解释将不胜感激,因为两天的网络搜索已证明没有结果。

回答

1
y = x 
x += 1 

BigInt是不可变的所以+1创建新的BigInt这就是为什么y不会改变。 y仍然指向前一个对象,而x指向新的BigInt对象。

5

x += 1will be expanded intox = x + 1所以它不仅是任务。

如果你将着眼于BIGINT的来源,你会看到+创建新实例:

def + (that: BigInt): BigInt = new BigInt(this.bigInteger.add(that.bigInteger)) 

实际上它使用Java的BigInteger,其添加操作留下两个参数不变的下方。

那么基本上发生在一天结束的时候是不可改变的另外的拷贝构造函数的结果参考再分配

+0

如果'x'没有定义一个名为'+ ='的方法,'x + = 1'只会扩展到'x = x + 1'。否则,该方法将被调用。 – 2013-04-12 00:40:49

0

我想它涉及到BigInt有与类似的类的不变性,你总是得到一个新的不可改变目的。