“!”的目的是啥?和 ”?”在方法名称的末尾?

Posted

技术标签:

【中文标题】“!”的目的是啥?和 ”?”在方法名称的末尾?【英文标题】:What is the purpose of "!" and "?" at the end of method names?“!”的目的是什么?和 ”?”在方法名称的末尾? 【发布时间】:2011-11-02 23:43:09 【问题描述】:

有时我会在 Ruby 中看到带有“?”的方法。和 ”!”在它们的末尾,例如:

name = "sample_string"
name.reverse
name.reverse!
name.is_binary_data?

我想知道他们的目的是什么?它们只是语法糖衣吗?

【问题讨论】:

Why are exclamation marks used in Ruby methods?的可能重复 【参考方案1】:

问号表示该方法返回布尔值。已经在这里回答了:

What does the question mark operator mean in Ruby?

bang 表示该方法作用于对象本身。已经在这里回答了:

Why are exclamation marks used in Ruby methods?

【讨论】:

【参考方案2】:

为了可读性,它“只是糖衣”,但它们确实具有共同的含义:

! 结尾的方法执行一些永久性或潜在危险的更改;例如: Enumerable#sort 返回对象的排序版本,而 Enumerable#sort! 将其排序。 在 Rails 中,ActiveRecord::Base#save 在保存失败时返回 false,而 ActiveRecord::Base#save! 会引发异常。 Kernel::exit 导致脚本退出,而Kernel::exit! 立即退出,绕过任何退出处理程序。 ? 结尾的方法返回一个布尔值,这使得代码流更加直观,就像一个句子——if number.zero? 读作“如果数字为零”,但if number.zero 看起来很奇怪。

在您的示例中,name.reverse 的计算结果为反向字符串,但只有在 name.reverse! 行之后,name 变量才真正包含反向名称。 name.is_binary_data? 看起来像“name 是二进制数据吗?”。

【讨论】:

一个重要的注意事项是,如果您也有相应的非 bang 方法,那么您应该只有一个 bang 方法。爆炸用于区分“更令人惊讶”的方法版本和“不那么令人惊讶”的方法。如果您只有一种方法,则无需区分,也不应以爆炸式命名。例如,请参阅Array#clear。它清除数组。清除数组自然会改变它。这并不奇怪,这个名字已经很清楚了,因此:没有爆炸。见ruby-forum.com/topic/176830#773946。 根据Ruby Style Guide,添加@JörgWMittag 所说的内容:潜在危险方法的名称(即修改自身或参数的方法,退出!(不运行终结器,如退出) ) 等) 应以感叹号结尾如果存在该危险方法的安全版本 请注意,情况并非总是如此。例如,Ruby Array#concat docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat。 MyActiveRecordModel.column_names.concat(...) 之类的东西会让你被严重烧伤。相反,您必须在执行 concat 之前克隆它。【参考方案3】:

在 Ruby 中,? 表示该方法将返回一个布尔值,! 修改了它被调用的对象。在查看代码时,它们可以提高可读性。

【讨论】:

【参考方案4】:

与 - 我想 - 大多数编程语言相比......

Ruby,方法允许以问号或感叹号结尾。

按照惯例,回答问题的方法(即 Array#empty? 如果接收者为空则返回 true)以问号结尾。

按照惯例,可能是“危险”的方法(即修改 self 或参数、exit!等的方法)以感叹号结尾。

来自:http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/,有趣的方法名称部分

【讨论】:

?结尾的方法也称为谓词方法。【参考方案5】:

请注意,情况并非总是如此。以 Ruby Array#concat http://docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat 为例。

MyActiveRecordModel.column_names.concat([url]) 之类的东西可能会让你被严重烧伤。稍后与 MyActiveRecordModel 相关的调用将尝试为 MyActiveRecordModel 查找“url”列并抛出。

相反,您必须在执行 concat 之前克隆它。幸运的是我的测试套件抓住了这个,但是.. 抬头!

【讨论】:

以上是关于“!”的目的是啥?和 ”?”在方法名称的末尾?的主要内容,如果未能解决你的问题,请参考以下文章

这个 [1] 在结构声明末尾的目的是啥?

addEventListener方法末尾的真假是啥意思

在 C++ 中从文件末尾读取的最有效方法是啥? (解析文件中的最后 128 位)

从第 n 项迭代到数组末尾的 Perlish 方法是啥?

仓库名称变更目的是啥

在 iOS 中实现新的“卡片”样式模态视图的真实名称和方法是啥?