我试图创建两种方法,其中一种方法会破坏性地添加" i"任何字符串,其中一个非破坏性地执行相同的操作。
def add_i(string)
new_string = string + "i"
end
def add_i!(string)
string = string + "i"
end
我的问题是:
这两种方法都是非破坏性的,即使我没有用新变量替换第二种方法中的参数。为什么呢?
一般来说,如何将非破坏性方法转换为破坏性方法,反之亦然?
答案 0 :(得分:4)
答案在于变量的范围和方法/运算符的行为。 add_i!中的左侧(左侧=)字符串与传入的字符串不同(右侧 > string 和方法arg)。旧字符串继续存在,但字符串var指向新字符串。
要使第二种方法“具有破坏性”,您可以执行以下操作:
def add!(string)
string << "i"
end
作为一个经验法则,您需要了解您所应用的方法/运算符是在操作数据本身还是返回数据的副本(例如楼上的'+'返回副本)
处理字符串并确保不破坏数据的简单方法是对传入的任何内容和之后使用dup()。
答案 1 :(得分:2)
问题是+
returns a copy of the string。我想这对于添加将返回两个数字的数字是有利的。 string += 'i'
也会制作副本。这有点令人惊讶,但它与数字相同。
您可以通过查看每个点的object_id
来看到这一点。
def add_i!(string)
puts "string passed into add_i! #{string.object_id}"
string = string + "i"
puts "string in add_i after + i #{string.object_id}"
end
foo = "blah"
puts "string about to be passed into add_i! #{foo.object_id}"
add_i!(foo)
puts "string after calling add_i! #{foo.object_id}"
string about to be passed into add_i! 70364940039240
string passed into add_i! 70364940039240
string in add_i after + i 70364940039020
string after calling add_i! 70364940039240
请注意,string in add_i after + i
具有不同的对象ID。
<<
和concat
都附加到现有字符串。 concat
应该是concat!
,但事实并非如此。