2013-04-11 57 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有與類似的類的不變性,你總是得到一個新的不可改變目的。