2015-10-06 69 views
3

我認爲當你聲明一個變量併爲它分配一個字符串或一個數組時,你正在製作一個該字符串或數組的獨立副本。此外,無論你對該變量做什麼都不會影響原始內容。我的假設不成立與第一組的代碼如下:Ruby將變量分配給一個數組的方式與賦給字符串的變量不同嗎?

array = ["tubular", "bell", "single", "file"] 
word = array[0] 
word[0] = word[0].upcase 
array.join(" ") # => Tubular bell single file 
word   # => Tubular 
array[0]  # => Tubular 

,但它確實第二:

string = "ten aviators climbing isoceles" 
word = string[0] 
word = word.upcase 
string # => ten aviators climbing isoceles 
word  # => T 
string[0] # => t 

有人能解釋爲什麼在第一組代碼,設置word[0]word[0].upcase導致原來分配給變量word的數組bell_arr發生了更改,但是類似的更改不會像第二組代碼中那樣通過指定字符串的變量發生?

回答

1

這是因爲word = string[0]創建了一個新的字符串實例。如果從字符串中取出的單個字符與原始字符串是相同的字符串實例,那麼這意味着原始字符串的內容已被該單個字符替換。這太不方便了。 Ruby的String#[]不這樣做。它創建一個新的字符串實例。此外,word = word.upcase只是一個變量賦值。它使用舊的word並創建一個新變量word。它不會對舊的word(首先與string不相同)做任何事情。

2

這是要處理我們稱之爲可變性/不可變性和編程語言中的對象引用。與「紅寶石」和「永恆」一些搜索,「引用」會帶來一些不錯的成績,但基本上

array = ["tubular bell single", "bell", "single", "file"] 

數組持有引用到一些Ruby對象,這裏String實例。 「Ruby字符串」實際上是String類的一個實例。您的數組包含對某些String實例的引用。

sentence = array[0] # Ruby terminal shows "tubular bell single" 
# But actually, array[0] is a reference to a Ruby Object 

數組[0]是對字符串Object的引用,即。數組[0]就像是一個指向字符串的指針。但是當你在你的Ruby終端中調用array[0]時,實際上你只是對字符串表示感興趣,而不是對象本身,所以在場景後面的Ruby調用類似array [0] .to_string的東西,這樣你就可以看到字符串,而不僅僅是例如#<Object:0x000000031082b0>,這是Ruby在終端中寫入對象引用並按Enter鍵時通常顯示的內容。

現在不像其他編程語言(如C),String類沒有任何「下面」,沒有「Character」類。一個String實例不是由其他Ruby對象的引用組成的。

當您調用「句子[0]」時,這基本上意味着您希望句子的第一個字母作爲可以操作的Ruby對象。所以它確實在內存中創建了一個新對象。

所以實際上first_letter = sentence[0]創建 String實例,這只是方含「T」

然而,當你調用句子[0] =「T」,您呼叫的特定方法的字符串字符串實例,基本上說:用這個替換這封信。當你這樣做時,你正在修改實例本身!

編輯:也許下面將會說清楚。紅寶石使用「對象標識符」,以確定每個對象的實例

a = "Hello World" 
b = "Hello again" 
c = "Hello World" # Same string representation as a 

a.object_id # 26817860 
b.object_id # 25401040 
c.object_id # 25247200 # Note it's not the same number as a! 

array = [a, b, c] 

array[0].object_id # 26817860, so it's the instance of a !! 

first_letter = a[0] # Ruby shows "H" 
first_letter.object_id # 23178100, a different object in memory 

現在

a = "A new string" 
a.object_id # 24367200, it's again new object in memory 
array # ["Hello World", "Hello again", "Hello World"] 
array[0].object_id # 26817860, our array[0] still points to the original object_id 

first_item = array[0] # "Hello World" 
first_item.object_id # 26817860 alright, no magic trick, this is still the object_id of "a" 
first_item[0] = "X" 
first_item.object_id # 26817860 UNCHANGED ! We have really changed our instance and not created a new one ! 
array # ["Xello World", "Hello again", "Hello World"] 
+0

「不過,爲了表示這一點,你需要一個新的字符串實例「 - 這不是造成差異的原因。我通過「像...... to_string'這樣的解釋」,你提到由'p'創建的檢查字符串。這些字符串是在兩種情況中的任何一種情況下新創建的,每次打印時都與這個問題無關。 – sawa

+0

@sawa感謝您指出這一點...現在好點了嗎? –

+0

@CyrilDD當你說「但是當你在你的Ruby終端中調用array [0]」時,會寫一個例子puts(array [0]? – user5415713

相關問題