“!”的目的是啥?和 ”?”在方法名称的末尾?
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 之前克隆它。幸运的是我的测试套件抓住了这个,但是.. 抬头!
【讨论】:
以上是关于“!”的目的是啥?和 ”?”在方法名称的末尾?的主要内容,如果未能解决你的问题,请参考以下文章