为什么一些Ruby方法需要爆炸而其他方法不是破坏性方法?

时间:2014-08-13 18:15:14

标签: ruby methods

例如,array.pop不需要爆炸来永久改变阵列。为什么会这样,在没有这种一致性的情况下开发这些某些Ruby方法背后的原因是什么?

4 个答案:

答案 0 :(得分:12)

Bang方法最常用于区分同一方法的危险版本和安全版本。以下是一些人们可能希望与bang / no-bang组合区分开的示例:

  • mutator方法 - 一个版本更改对象,另一个版本返回副本并保持原始对象不变
  • 遇到错误时,一个版本抛出异常,而另一个版本只将错误消息写入日志或什么都不做

然而,如果只有一个版本有意义,那么惯例就是让关闭。例如,pop数组而不实际更改它是没有意义的。在这种情况下,它最终将成为一个不同的操作:Array#last。许多方法都会更改它们所调用的对象,例如setter。我们也不需要用一声巨响来写这些,因为很明显他们会改变对象。

最后,有一些例外情况,一些开发人员可能会使用bang方法而不实现无需对手。在这些情况下,爆炸只是用来使方法调用在视觉上突出。例如:

  • 该方法做了危险或破坏性的事情
  • 该方法有意外的事情
  • 该方法具有显着的性能影响

答案 1 :(得分:2)

爆炸用于区分同一方法的危险版本和危险版本。只有一种pop方法,因此无需区分。

注意:该方法的名称绝对没有任何关系。方法是否具有破坏性取决于它执行的代码,而不是它的名称。

答案 2 :(得分:1)

后缀!表示方法是另一种方法的危险版本。例如,save!save的危险版本。 Dangerous可能意味着编辑到位,执行更严格的错误等等。不需要在危险的方法上使用!后缀,但不需要更安全的对应方法。此外,这只是一个命名约定,因此如果方法以!结束或不以!结束,Ruby不会限制您可以做什么和不能做什么。

有一种常见的误解,即编辑某些内容的每种方法都应以!结尾。事实并非如此,只有在存在更危险版本的方法时才需要ActiveRecord::Base#save!,这并不一定意味着危险方法已编辑到位。例如,在Rails中,ActiveRecord::Base#save是执行验证的{{1}}版本。

答案 3 :(得分:1)

Ruby中bang的含义是“谨慎”。这意味着您应该谨慎使用该方法,仅此而已。我再也找不到参考,但有权威的人明确表示,砰是破坏性的方法。 Bang只是一个与谨慎相关的语义元素。程序员需要权衡一切并决定何时使用爆炸。

例如,在我的模拟gem中,我使用#step方法来获取步长。

simulation.step #=> 0.42

step!方法实际执行模拟步骤。

simulation.step! #=> takes the simulation to the next time step

但至于#reset方法,我认为“重置”这个词足够详细,并且没有必要使用bang来警告用户模拟状态将被破坏:

simulation.reset #=> resets the simulation back to the initial state

P.S。:现在我记得,曾经有一段时间,Matz半开玩笑说他后悔将方法引入Ruby中,因为bang在语义上是如此模糊。