更改ruby变量/引用的值
我偶然发现了一些我不太了解的事情。 我知道ruby中的变量是引用。 所以很棒的东西是可能的。 但是当我将变量传递给方法时,它表现得很奇怪:
my_var_a = "nothing happend to me" my_var_b = "nothing happend to me" def parse_set(my_var_set) my_var_set = "my value changed" end def parse_sub(my_var_sub) my_var_sub.sub! /(.*)/, "my value changed" end parse_set(my_var_a) parse_sub(my_var_b) my_var_a # => "nothing happend to me" my_var_b # => "my value changed"
你能解释一下为什么它适用于sub!
和=
保持对象不变? 我怎么能避免使用sub!
但结果相同?
my_var_a
和my_var_set
是不同的引用,但它们指向同一个对象。 如果修改my_var_set
的对象,则更改将显示在my_var_a
。 但是,如果您在新对象上重新指定my_var_set
,则不会更改my_var_a
指向的内容。
编辑:澄清……
Ruby所做的是通过值传递引用。 当你说
my_var_a = "nothing happend to me"
Ruby在内存位置保存字符串“没有任何事情发生在我身上”(让我们称之为1000),并将my_var_a
引用保存在另一个内存位置(比方说2000)。 当您的代码使用my_var_a
,解释器会查看位置2000,看它指向1000,然后从1000获取实际的字符串值。
当你调用parse_set(my_var_a)
,Ruby实际上会创建一个名为my_var_set
的新引用, my_var_a
其指向my_var_a
指向的字符串(内存位置1000)。 但是, my_var_set
是my_var_a
引用的副本 – 假设my_var_set
是在内存位置3000创建的my_var_a
和my_var_set
是内存中2个完全不同的引用,它们恰好指向保存字符串值的同一个精确内存位置。
my_var_set = "my value changed"
的语句my_var_set = "my value changed"
在parse_set
创建一个新字符串,并将my_var_set
指向该新内存位置。 但是,这不会改变原始my_var_a
参考指向的内容! 既然my_var_set
指向不同的内存位置,那么您对该变量所做的任何操作都不会影响my_var_a
。
对于parse_sub
也会发生相同的引用副本。 但是parse_sub
更改字符串的原因是因为您直接在my_var_sub
引用上调用方法。 执行此操作时,解释器将获取my_var_sub
指向的对象,然后对其进行修改。 因此,更改将显示在my_var_a
引用中,因为它仍指向相同的字符串。
irb(main):008:0* a = 'abc' => "abc" irb(main):009:0> a.replace('def') => "def" irb(main):010:0> a => "def"
在我用Ruby编程的这些年里,我不得不使用replace
完全零次。 我想知道你的代码是否有更好的设计。
更改接收器的大多数字符串方法都带有后缀! (sub!,大写!,chomp!等)有些更改接收器的内容不是后缀! (替换是一个)。 如果调用更改接收器的方法,则对该对象的任何和所有引用都将看到更改。 如果调用不更改接收器的方法,则该方法返回一个新字符串 。
gsub不会修改接收器,而是返回一个新的String实例:
a = "foo" b = a p a.sub(/o/, '#') # "f##" pa # => "foo" pb # => "foo"
GSUB! 修改接收器:
a = "foo" b = a p a.sub!(/o/, '#') # => "f#o" pa # => "f#o" pb # => "f#o"
“我怎样才能避免使用sub!但结果相同?”
def parse_set() "my value changed" end a = parse_set()
将它设置为对象的实例变量(虽然这只适用于您的主脚本,但如果您想使用实例变量方法,我建议您创建自己的类)。
@my_var_a = "nothing happend to me" def parse_set() @my_var_a = "my value changed" end