2016-04-10 55 views
0

我想確認一下我的理解是否正確的代碼,這六個行的「複製」紅寶石陣的變化:通過改變它的元素之一

string="this is a sentence" 
words=string.split 
first_word=words[0] 
first_word[0]=first_word[0].upcase 
out=words.join(" ") 
puts(out) 

它打印「這是一個句子」 (首字母大寫)。

看來,改變「first_word」字符串,它被定義爲「words」數組的第一個元素,也會改變原來的「words」數組。這確實是Ruby的默認行爲?它是否會讓跟蹤代碼在陣列中發生更改的位置變得更難?

+1

你正在給數組元素分配一個新的字符串。一個數組不是一個不可變的元組。爲什麼你感到驚訝*分配一個新的值*分配一個新的值? –

回答

1

您只需要區分變量和對象。你的字符串是一個對象。 first_word是一個變量。

查找例如

a = "hello" 
b = a 
c = b 

現在所有變量包含相同對象,其值爲「你好」的字符串。我們說他們參考的對象。沒有複製。

a[0] = 'H' 

這改變了對象的第一個字符,它目前擁有的價值「你好」的字符串。 bc都包含相同的,現在已更改的對象。

a = "different" 

這會爲變量a分配一個新對象。 bc仍然保留原始對象。

這是Rubys的默認行爲?是。而且它在許多其他編程語言中也是這樣工作的。

它是否難以追蹤變化?有時。

如果從數組需要一個元素(如您的first_word),你需要知道:

如果你改變物體本身,無論你如何訪問它, 所有變量仍然會牽着你的對象,剛好發生了變化。

但是,如果您替換數組中的對象,如words[0] = "That",那麼您的所有其他變量仍將保留原始對象。

+0

感謝Meier,簡單的解釋。 –

0

此行爲是由ruby如何傳遞值和傳遞引用引起的。

這可能是Ruby更令人困惑的部分之一。 Ruby被廣泛接受是一種傳值,高級編程語言。不幸的是,這有點不正確,你發現自己是一個完美的例子。 Ruby確實按值傳遞,但是,ruby中的大多數值都是引用。當Ruby完成一個簡單數據類型,整數,浮點數,字符串的賦值時,它將創建一個新對象。但是,在分配數組和哈希等對象時,您正在創建引用。

original_hash = {name: "schylar"} 
reference_hash = original_hash 
reference_hash[:name] = "!schylar" 
original_hash #=> "!schylar" 

original_array = [1,2] 
reference_array = original_array 
reference_array[0] = 3 
reference_array #=> [3,2] 

original_fixnum = 1 
new_object_fixnum = original_fixnum 
new_object_fixnum = 2 
original_fixnum #=> 1 

original_string = "Schylar" 
new_object_string = original_string 
new_object_string = "!Schylar" 
original_string #=> "Schylar' 

如果您發現自己需要按價值複製,您可能會重新考慮設計。傳遞複數數據類型的常用方法是使用Marshal方法。

a = {name: "Schylar"} 
b = Marshal.load(Marshal.dump(a)) 
b[:name] = "!!!Schylar" 
a #=> {:name => "Schylar"} 
+0

是否認爲它有助於談論編組對某些似乎尚未理解變量和對象之間區別的人? – Meier

+0

目的不是談論編組,而是介紹一種可接受的方式來複制價值。 – Schylar

+2

需要說明的是,這是「通過對象引用」,實際上它是由object_id表示的指針,儘管這種區別在很大程度上是看不見的。 – tadman

相關問題