Яка мета "!" і "?" наприкінці назв методів?


99

Іноді в Рубі я бачу методи, які мають "?" і "!" наприкінці їх, наприклад:

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

Мені було цікаво, яке їх призначення? Вони просто синтаксис цукрового покриття?


Відповіді:


160

Це "просто цукрове покриття" для читабельності, але вони мають загальне значення:

  • Способи, що закінчуються !виконанням якоїсь постійної або потенційно небезпечної зміни ; наприклад:
    • Enumerable#sortповертає відсортовану версію об'єкта, при цьому Enumerable#sort!сортує його на місці.
    • У Rails ActiveRecord::Base#saveповертає помилку, якщо збереження не вдалося, а ActiveRecord::Base#save!збільшує виняток.
    • Kernel::exitвикликає вихід сценарію, але Kernel::exit!робить це негайно, минаючи будь-які обробники виходів.
  • Методи, що закінчуються ?взамін булевими , що змушує код надходити ще більш інтуїтивно, як речення - if number.zero?читається як "якщо число дорівнює нулю", але if number.zeroпросто виглядає дивно.

У вашому прикладі name.reverseоцінюється на зворотній рядок, але лише після того, як name.reverse!рядок nameдійсно містить змінну назву. name.is_binary_data?виглядає як "це nameдвійкові дані?".


22
Одне важливе зауваження полягає в тому, що у вас повинен бути метод удару, лише якщо у вас є відповідний метод, який не стосується удару. Вибух використовується для того, щоб відрізняти "більш дивну" версію методу від "менш дивної". Якщо у вас є лише один метод, то розрізнення не потрібно, і ви не повинні називати його з ударом. Див. Array#clear, Наприклад. Це очищає масив. Очищення масиву природно мутує його. У цьому немає нічого дивного, ім'я вже дає зрозуміти, отже: жодного удару. Див. Ruby-forum.com/topic/176830#773946 .
Йорг W Міттаг

2
Додаючи до того, що заявив @ JörgWMittag, відповідно до посібника по стилю Ruby : Назви потенційно небезпечних методів (тобто методів, що змінюють «self» або «аргументи, вихід!» (Не запускає фіналізатори, як це робить exit) тощо). знак оклику, якщо існує безпечна версія цього небезпечного методу .
Tod Birdsall

2
Остерігайтеся, це не завжди так. Наприклад, Ruby Array # concat docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat . Там, де можна погано згоріти, є щось на кшталт MyActiveRecordModel.column_names.concat (...). Натомість ви повинні клонувати його перед тим, як робити конват.
wintondeshong


8

У Ruby ?означає, що метод збирається повернути булевий і !модифікує об'єкт, на який він викликався. Вони там, щоб поліпшити читабельність при перегляді коду.


5

На відміну від - я думаю - більшості мов програмування ...

Рубі, методи дозволяється закінчувати знаками запитання або знаками оклику.

За умовою, методи, які відповідають на запитання (тобто Array # empty? Повертає true, якщо приймач порожній), закінчуються знаками запитань.

Потенційно «небезпечні» методи (тобто методи, що змінюють «я» або «аргументи», «вихід!») За умовами закінчуються знаками оклику.

Від: http://www.ruby-lang.org/uk/documentation/ruby-from-other-languages/ , розділ Імена прикольних методів


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, спробують шукати стовпчик 'url' для MyActiveRecordModel і кидають.

Натомість ви повинні клонувати його перед тим, як робити конват. На щастя, мій тестовий набір зловив цього, але .. голова!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.