「!」の目的は何ですか そして「?」メソッド名の最後に?


99

Rubyで「?」を持つメソッドが見つかることがあります。そして「!」それらの終わりに、例えば:

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

彼らの目的は何だろうと思っていましたか?それらは構文糖衣だけですか?


回答:


160

読みやすくするために「単なる糖衣」ですが、共通の意味があります。

  • で終わるメソッドは!、永続的または潜在的に危険な変更を実行します。例えば:
    • Enumerable#sort並べ替えられたオブジェクトのバージョンを返しますEnumerable#sort!
    • Railsでは、ActiveRecord::Base#save保存に失敗した場合はfalseを返しActiveRecord::Base#save!、例外が発生します。
    • Kernel::exitスクリプトを終了さKernel::exit!せますが、すぐに終了し、終了ハンドラーをバイパスします。
  • 末尾が?Booleanのメソッドは、コードの流れを文のようにさらに直感的にしif number.zero?ます。「数値がゼロの場合」のように読みますが、if number.zero奇妙に見えます。

あなたの例でname.reverseは、反転した文字列に評価されますが、name.reverse!行の後にのみ、name実際に変数は反転した名前を含みますname.is_binary_data?nameバイナリデータですか?」のように見えます。


22
重要な注意点の1つは、対応する非bangメソッドもある場合にのみbangメソッドを使用する必要があることです。ビッグバンは、メソッドの「驚くべき」バージョンと「驚くべきでない」バージョンを区別するために使用されます。メソッドが1つしかない場合は、区別する必要はありません。メソッド名を強打してはいけません。Array#clearたとえば、を参照してください。配列をクリアします。配列をクリアすると、自然に変化します。それについては驚くべきことは何もありません。そのため、その名前からすでに明確になっています。ruby-forum.com/topic/176830#773946を参照してください。
イェルクWミッターク

2
Rubyスタイルガイドによると、@JörgWMittagの記述に追加:潜在的に危険なメソッド(つまり、自己または引数を変更するメソッド、exit!(exitのようにファイナライザを実行しない)など)の名前はその危険なメソッドの安全なバージョンが存在する場合の感嘆符。
Tod Birdsall 2015年

2
注意してください、これは常にそうだとは限りません。たとえば、Ruby Array#concat docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concatです。あなたがひどく燃えることができる場所は、MyActiveRecordModel.column_names.concat(...)のようなものです。代わりに、連結を行う前にクローンを作成する必要があります。
wintondeshong 2016


8

Rubyでは?、メソッドがブール値を返し、!呼び出されたオブジェクトを変更することを意味します。それらは、コードを見たときに読みやすさを向上させるためにあります。


5

-とは対照的に-ほとんどのプログラミング言語...

Rubyでは、メソッドの最後に疑問符または感嘆符を付けることができます。

慣例により、質問に答えるメソッド(つまり、Array#empty?はレシーバが空の場合にtrueを返します)は疑問符で終わります。

慣例により、潜在的に「危険な」メソッド(つまり、自分自身または引数を変更するメソッド、exit!など)は感嘆符で終わります。

From:http : //www.ruby-lang.org/en/documentation/ruby-from-other-languages/、セクションFunnyのメソッド名


1
また、で終わる?メソッドは述語メソッドと呼ばれます。
Waseem

1

注意してください、これは常にそうだとは限りません。たとえば、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」の列を探してスローしようとします。

代わりに、連結を行う前にクローンを作成する必要があります。幸い、私のテストスイートはこれを検出しましたが、前向きです。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.