【发布时间】:2013-04-24 11:38:52
【问题描述】:
我正在尝试通过阅读代码来学习 Ruby,但我遇到了以下情况,在我的任何教程/备忘单中都找不到。
def foo!
# do bar
return bar
end
“!”的意义何在?在方法定义中?
【问题讨论】:
-
Ruby 方法定义体开头的
//是什么意思?
标签: ruby
我正在尝试通过阅读代码来学习 Ruby,但我遇到了以下情况,在我的任何教程/备忘单中都找不到。
def foo!
# do bar
return bar
end
“!”的意义何在?在方法定义中?
【问题讨论】:
// 是什么意思?
标签: ruby
! 是一个“bang”方法,它改变了接收者,是 Ruby 中的一个约定。
您可以定义一个! 版本,它可能像非爆炸方法一样工作,但如果其他程序员不查看您的方法定义,就会误导他们。
当接收者没有改变时,bang 方法又返回nil。
没有!的例子——你可以看到源字符串没有改变:
str = "hello"
p str.delete("l") #=> "heo"
p str #=> "hello"
! 的示例 - 您可以看到源字符串已更改:
str = "hello"
p str.delete!("l") #=> "heo"
p str #=> "heo"
注意:有一些非 bang 版本的方法,也可以改变接收者对象:
str = "hello"
p str.concat(" world") #=> "hello world"
p str #=> "hello world"
【讨论】:
! 表示该方法是另一种方法的潜在危险版本。很多时候,! 确实修改了接收器(这是危险的),但其他时候会发生其他影响。例如,在 Rails 中,ActiveRecord save 和 save! 都修改了接收器(在某种意义上),但 save! 方法可能会引发异常。吉姆·斯图尔特的答案是正确的答案。
nil。这个问题被标记为Ruby。所以根据 ruby,我写的 bang 方法就是这样。
Ruby 不会将! 视为方法名称末尾的特殊字符。按照惯例,以! 结尾的方法具有某种副作用或方法作者试图引起注意的其他问题。示例是执行就地更改、可能引发异常或不顾警告继续执行操作的方法。
例如,String#upcase! 与 String#upcase 的比较如下:
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 相比,它返回 true/false 但不会引发异常)。
这是一个“抬头!”标志,但没有什么可以强制执行此操作。如果您想迷惑和/或吓唬人们,您可以在 ! 中结束您的所有方法。
【讨论】:
! 方法往往具有不同的返回值(最明显的是 nil,当没有任何变化时)这可能会导致意外和微妙的错误。
! 不是方法定义,而是声明方法时使用的约定,此方法将更改对象。
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"
【讨论】: