感叹号和函数内部的赋值

时间:2015-09-29 17:14:09

标签: ruby

有人可以解释为什么:

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

4 个答案:

答案 0 :(得分:3)

由于Ruby传递参数的方式。

调用方法时,您有两个引用str_mainstr到同一个对象"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成为实例变量的方式类似。