在Ruby中,有些方法带有问号(?),会问include?询问是否包含有问题的对象,然后返回true/false。
但是为什么有些方法有感叹号(!)而其他方法没有呢?
这是什么意思?
在Ruby中,有些方法带有问号(?),会问include?询问是否包含有问题的对象,然后返回true/false。
但是为什么有些方法有感叹号(!)而其他方法没有呢?
这是什么意思?
当前回答
通常,以!结尾的方法指示该方法将修改调用它的对象。Ruby将这些方法称为“危险方法”,因为它们更改了其他人可能引用的状态。下面是一个简单的字符串示例:
foo = "A STRING" # a string called foo
foo.downcase! # modifies foo itself
puts foo # prints modified foo
这将输出:
a string
在标准库中,您可以在很多地方看到名称相似的方法对,其中一个带有!一个没有。没有安全方法的方法被称为“安全方法”,它们返回原始方法的副本,其中对副本进行了更改,而被调用者没有更改。下面是没有使用!的相同示例:
foo = "A STRING" # a string called foo
bar = foo.downcase # doesn't modify foo; returns a modified string
puts foo # prints unchanged foo
puts bar # prints newly created bar
这个输出:
A STRING
a string
请记住,这只是一种约定,但许多Ruby类都遵循它。它还可以帮助您跟踪代码中修改的内容。
其他回答
它是最准确的说,方法与Bang!是更危险或更令人惊讶的版本。有很多方法在没有Bang的情况下会发生突变,比如.destroy,通常情况下,方法只有Bang,而核心库中存在更安全的替代方法。
例如,在Array中,我们有.compact和.compact!,这两个方法都会改变数组,但是.compact!如果数组中没有nil则返回nil而不是self,这比只返回self更令人惊讶。
我发现唯一的非突变方法是Kernel的.exit!这比.exit更令人惊讶,因为你无法在进程关闭时捕获SystemExit。
Rails和ActiveRecord延续了这一趋势,因为它使用bang来实现更多“令人惊讶”的效果,如.create!这会在失败时产生错误。
!
我喜欢把这看作是一个爆炸性的变化,它摧毁了之前的一切。Bang或感叹号表示您正在对代码进行永久保存的更改。
如果你使用Ruby的方法进行全局替换,sub!你所做的替换是永久的。
你可以想象的另一种方式是,打开一个文本文件,进行查找和替换,然后保存。! 在代码中执行相同的操作。
如果您来自bash世界,另一个有用的提醒是sed -i具有永久保存更改的类似效果。
从themomorohoax.com:
刘海有以下几种用法,依我个人喜好而定。
如果活动记录方法没有这样做,则会引发错误 就像它说的那样。 活动记录方法保存记录或方法保存 对象(例如strip!) 方法做一些“额外的”事情,比如张贴到某个地方 一些行动。
关键是:只有在你真正想过是否要使用爆炸的时候 这是必要的,可以省去其他开发人员不得不这样做的烦恼 检查你为什么要使用爆炸声。
爆炸为其他开发者提供了两个线索。
方法调用后,没有必要保存对象 方法。 当你调用这个方法时,db会被改变。
通常,以!结尾的方法指示该方法将修改调用它的对象。Ruby将这些方法称为“危险方法”,因为它们更改了其他人可能引用的状态。下面是一个简单的字符串示例:
foo = "A STRING" # a string called foo
foo.downcase! # modifies foo itself
puts foo # prints modified foo
这将输出:
a string
在标准库中,您可以在很多地方看到名称相似的方法对,其中一个带有!一个没有。没有安全方法的方法被称为“安全方法”,它们返回原始方法的副本,其中对副本进行了更改,而被调用者没有更改。下面是没有使用!的相同示例:
foo = "A STRING" # a string called foo
bar = foo.downcase # doesn't modify foo; returns a modified string
puts foo # prints unchanged foo
puts bar # prints newly created bar
这个输出:
A STRING
a string
请记住,这只是一种约定,但许多Ruby类都遵循它。它还可以帮助您跟踪代码中修改的内容。
简单的解释:
foo = "BEST DAY EVER" #assign a string to variable foo.
=> foo.downcase #call method downcase, this is without any exclamation.
"best day ever" #returns the result in downcase, but no change in value of foo.
=> foo #call the variable foo now.
"BEST DAY EVER" #variable is unchanged.
=> foo.downcase! #call destructive version.
=> foo #call the variable foo now.
"best day ever" #variable has been mutated in place.
但是如果你曾经用downcase来调用一个方法!在上面的解释中,foo将永久地更改为downcase。downcase !不会返回一个新的字符串对象,而是在适当的位置替换字符串,完全将foo更改为downcase。 我建议你不要用小写!除非完全有必要。