Ruby方法最后的!是什么意思

What does ! mean at the end of a Ruby method definition?

本问题已经有最佳答案,请猛点这里访问。

我试图通过阅读代码来学习Ruby,但我遇到了以下情况,在我的教程/练习表中都找不到。

1
2
3
4
5
def foo!
    # do bar

    return bar  
  end

"!"的意思是什么?在方法定义中?


Ruby不将!作为方法名末尾的特殊字符。按照惯例,以!结尾的方法有一些副作用或其他问题,这正是作者试图引起注意的。示例是执行就地更改的方法,或者可能引发异常,或者在出现警告的情况下继续执行操作。

例如,下面是String#upcase!String#upcase的比较方式:

1
2
3
4
5
6
7
8
9
10
1.9.3p392 :004 > foo ="whatever"
 =>"whatever"
1.9.3p392 :005 > foo.upcase
 =>"WHATEVER"
1.9.3p392 :006 > foo
 =>"whatever"
1.9.3p392 :007 > foo.upcase!
 =>"WHATEVER"
1.9.3p392 :008 > foo
 =>"WHATEVER"

ActiveRecord广泛使用Bang方法来处理诸如save!之类的问题,它在失败时引发异常(与save相反,后者返回真/假,但不引发异常)。

这是一个"抬头!"旗子,但没有什么能强制执行。如果你想迷惑和/或吓唬人,你可以在!中结束你所有的方法。


!是一种"bang"方法,它改变了接收器,是ruby中的约定。

您可以定义一个!版本,它可能像一个非Bang方法一样工作,但是如果其他程序员不看您的方法定义,它就会误导他们。

当没有对接收器进行任何更改时,Bang方法依次返回nil

不带!的示例-可以看到源字符串没有更改:

1
2
3
str ="hello"
p str.delete("l") #=>"heo"
p str #=>"hello"

使用!的示例-可以看到源字符串已更改:

1
2
3
str ="hello"
p str.delete!("l") #=>"heo"
p str #=>"heo"

注:有一些非Bang版本的方法,也可以更改接收器对象:

1
2
3
str ="hello"
p str.concat(" world") #=>"hello world"
p str #=>"hello world"


!不是方法定义,而是在声明方法时使用的约定,此方法将更改对象。

1
2
3
4
5
6
7
8
9
10
1.9.3-p194 :004 > a="hello"
 =>"hello"
1.9.3-p194 :005 > a.strip
 =>"hello"
1.9.3-p194 :006 > a
 =>"hello"
1.9.3-p194 :007 > a.strip!
 =>"hello"
1.9.3-p194 :008 > a
 =>"hello"