簡體   English   中英

淺表復制如何在Smalltalk中用於Array?

[英]How does shallow copy work for Array in Smalltalk?

因此,據我了解,當您將消息copy傳遞給數組時,將執行淺表副本。 兩個對象應該指向同一個數組,理論上,當您更改一個數組時,您將更改另一個數組。 但是,當我運行此代碼時,它的行為就像是一個深層副本。 每個陣列彼此獨立。 我在第一個數組中進行更改,而第二個數組不受影響。 我在第二個數組中進行更改,而第一個數組不受影響。 那么當我使用copy時,復印實際上如何工作?

| a b |

a := #('first' 'second' 'third').
b := a copy.
Transcript show: a = b;cr.
Transcript show: a == b;cr.
Transcript show: (a at: 1) == (b at: 1);cr.
b at: 1 put: 'newFirst'.
Transcript show: a;cr.
Transcript show: b;cr.
Transcript show: (a at: 1) == (b at: 1);cr.
a at: 2 put: '2nd'.
Transcript show: a;cr.
Transcript show: b;cr.
a := nil.
Transcript show: a;cr.
Transcript show: b;cr.

結果是:

true
false
true
#('first' 'second' 'third')
#('newFirst' 'second' 'third')
false
#('first' '2nd' 'third')
#('newFirst' 'second' 'third')
nil
#('newFirst' 'second' 'third')

復制操作確實會創建數組的淺表副本。 這意味着將創建一個新數組,該數組引用與原始數組相同的對象(“內容”)。

通過at:put:更改副本at:put: ,原始數組不會受到影響,因為其引用未更改。 此外,更改副本的引用不會更改所包含的對象本身。 相反,該副本現在僅引用其他對象(在您的情況下為'newFirst''2nd' )。 這是為什么將新對象放入副本中而不會影響原始數組的內容的另一個原因。

但是,由於這是一個淺表副本,因此不會復制原始數組中的字符串。 您可以觀察到以下情況:

a := Array with: (String newFrom: 'first') with: 'second' with: 'third'.
b := a copy.
(a at: 1) replaceFrom: 1 to: 5 with: '1st  '.  "in-place modification"
Transcript show: a = b; cr. "true"
Transcript show: (a at: 1); cr. "1st  "
Transcript show: (b at: 1); cr. "1st  "
Transcript show: (a at: 1) == (b at: 1); cr. "true"

此處,數組的副本未更改,但是原始數組及其副本的公共元素之一已更改。 如果復制操作較深,則第三行上的更改不會影響b at: 1 它會指向另一個字符串。


上面的代碼中的String newFrom:可以避免修改字符串文字“ first”。

因此,據我了解,當您將消息副本傳遞給數組時,將執行淺表副本。 兩個對象應該指向同一個數組,理論上,當您更改一個數組時,您將更改另一個數組。

這是你的錯誤。 確實,副本會產生淺表副本,但是您對淺表副本的理解是錯誤的。 淺表副本將為您提供該對象的新實例,但是所有實例變量將繼續指向相同的對象。 實際上,您僅創建一個新對象。

如果您希望變量“ a”和“ b”指向同一個對象,您要做的就是將它們彼此分配:

b := a.

這將使您修改“ b”,並使更改也影響“ a”。

為了進一步擴展該概念,您需要使用deepCopy和deepDeepCopy等概念。這些變化背后的想法是,它們也為實例變量創建新的對象。

從技術上講,諸如Array,OrderedCollection,String等的索引對象不使用實例變量,但是概念是相同的-deepCopy復制了復制對象所指向的對象。 deepDeepCopy將更進一步,並復制那些指向對象。

看看這是否對您更有意義:

|a b|
a := #('first' 'second' 'third').
b := a copy.
(b at: 1) at: 1 put: $X.
a at: 2 put: '2nd'.
Transcript show: a; cr.
Transcript show: b; cr.

...產生以下輸出:

#('Xirst' '2nd' 'third')
#('Xirst' 'second' 'third')

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM