有人可以解释为什么:
def do_something str
str = "bar"
end
str_main = "foo"
do_something str_main
puts str_main
显示foo
?
而且:
def do_something str
str.capitalize!
end
str_main = "foo"
do_something str_main
puts str_main
显示Foo
?
答案 0 :(得分:3)
由于Ruby传递参数的方式。
调用方法时,您有两个引用str_main
和str
到同一个对象"foo"
。
在第一个示例中,当您使用str = "bar"
时,您只需更改str
引用所指向的内容。现在你有了str_main -> "foo"
和str -> "bar"
。因此,原始对象不会更改。
在第二个示例中,您没有更改str
引用并使用mutator method更改了字符串,从而更改了str_main
指向的同一对象。
答案 1 :(得分:1)
感叹号或爆炸操作符会修改原始值。这是一种破坏性的方法。例如,让我们说你有一个字符串
string = "hi";
如果您调用upcase
方法,您将获得以下
string.upcase
=> "HI"
但是,如果再次调用字符串,则会得到初始值。
string
=> "hi"
现在,让我们假设您使用破坏性方法upcase!
string.upcase!
=> "HI"
现在,如果再次调用字符串,您将看到该值已发生变异。
string
=> "HI"
答案 2 :(得分:1)
在Ruby中,引用按值传递。因此,对str_main
的引用传递给方法do_something
,引用的副本存在于变量str
中。
但是,这并不意味着两个变量引用的值也被复制了 - 仍然只有一个引用值的副本,即Main
中定义的字符串。
因此,当您为str
分配新值时,这不会改变str_main
的值。但是,当您修改str
引用的值时,其更改可在外部进行查看。
答案 3 :(得分:1)
所有ruby方法都返回最后评估的东西。但是,对象分配仍在当前代码块的范围内。将str_main
分配给方法中的新值不会影响str_main
,除非它是实例变量(@str_main
)。这样做可以让您在程序的范围或深度范围内重新分配对象。这就是您的第一种方法输出'foo'
而不是'bar'
。
现在,第二个例子。 #capitalize
是一个在字符串对象上调用的方法。它返回一个 new String
实例,其值为原始对象大写。
string = 'foobar'
string.capitalize # => 'Foobar'
puts string # => 'foobar'
请注意string
如何仅暂时修改,再次调用时它会恢复正常。
ruby中的许多方法都以!
结尾。此约定与:object = object.some_method
相同。这些方法不是创建对象的新实例,而是编辑原始对象的值。对于#capitalize!
,字符串大写并修改以供将来调用。
string = 'foo'
string.capitalize! # => 'Foo'
puts string # => 'Foo'
回到第二个例子。使用#capitalize!
范围内的do_something
方法可以修改str_main
对象。与使str_main
成为实例变量的方式类似。