我认为当你声明一个变量并为它赋一个字符串或数组时,你就是在创建一个字符串或数组的独立副本。此外,无论你对该变量做什么都不会影响原始变量。我的假设不适用于下面的第一组代码:
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
会导致我最初分配给变量bell_arr
的数组word
发生更改,但是在第二组代码中,如果变量分配了一个字符串,则不会发生类似的变化?
答案 0 :(得分:2)
这必须处理我们在编程语言中称为可变性/不可变性和对象引用的问题。使用" Ruby"进行一些搜索和"不变性","参考"会带来一些好的结果,但基本上
array = ["tubular bell single", "bell", "single", "file"]
数组包含对某些Ruby对象的引用,这里是String
个实例。 A" Ruby字符串"实际上是String类的一个实例。您的数组包含对String的某些实例的引用。
sentence = array[0] # Ruby terminal shows "tubular bell single"
# But actually, array[0] is a reference to a Ruby Object
Array [0]是对字符串Object的引用,即。 array [0]就像一个指向字符串的指针。但是当你在Ruby终端中调用array[0]
时,你实际上只对字符串表示感兴趣,而不是对象本身,所以在场景后面的Ruby调用了类似array [0] .to_string的东西,所以你可以看到字符串,而不仅仅是像#<Object:0x000000031082b0>
这样的东西,这是Ruby在您的终端中写入对象的引用并按下回车时通常显示的内容。
现在不像其他编程语言(如C),下面没有&#34;&#34;一个String类,没有&#34;字符&#34;类。 String实例不是由对其他Ruby对象的引用组成的。
当您调用&#34;句子[0]&#34;时,这基本上意味着您希望将句子的第一个字母作为可以操作的Ruby对象。所以它确实在内存中创建了一个新的对象。
所以实际上first_letter = sentence[0]
创建了一个新字符串实例,它只是包含&#34; t&#34;
但是,当你调用句子[0] =&#34; t&#34;时,你正在调用String实例上的一个特定方法,它基本上是这样的:用这个替换这个字母。执行此操作时,您正在修改实例本身!
编辑:也许以下内容会说清楚。 Ruby使用&#34;对象标识符&#34;识别每个对象的实例
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"]
答案 1 :(得分:1)
这是因为word = string[0]
创建了一个新的字符串实例。如果从字符串中取出的单个字符与原始字符串是相同的字符串实例,那么这意味着原始字符串的内容已被该单个字符替换。这太不方便了。 Ruby的String#[]
不会这样做。它创建一个新的字符串实例。此外,word = word.upcase
只是一个变量赋值。它使用旧的word
并创建一个新变量word
。它对旧的word
没有任何作用(首先与string
不同)。