Какова цель «!» и "?" в конце имен методов?

99

Иногда я вижу в Ruby методы, в которых есть "?" и "!" в конце, например:

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

Мне было интересно, какова их цель? Они просто приукрашивают синтаксис?

itsaboutcode
источник

Ответы:

160

Это «просто приукрашивание» для удобства чтения, но у них есть общие значения:

  • Методы, заканчивающиеся !выполнением какого-либо постоянного или потенциально опасного изменения ; например:
    • 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двоичные данные?».

jtbandes
источник
22
Одно важное замечание: у вас должен быть только метод взрыва, если у вас есть соответствующий метод без взрыва. Челка используется, чтобы отличить «более удивительную» версию метода от «менее удивительной». Если у вас есть только один метод, то нет необходимости в различении, и не стоит называть его на ура. См. Array#clearНапример. Очищает массив. Очистка массива естественным образом изменяет его. Ничего удивительного в этом нет, поэтому название уже ясно дает понять: никакого взрыва. См. Ruby-forum.com/topic/176830#773946 .
Jörg W Mittag
2
Добавление к тому, что заявил @ JörgWMittag, согласно Руководству по стилю Ruby : имена потенциально опасных методов (т.е. методов, которые изменяют self или аргументы, exit! (Не запускают финализаторы, как exit) и т. Д.) Должны заканчиваться на восклицательный знак, если существует безопасная версия этого опасного метода .
Tod Birdsall
2
Остерегайтесь, это не всегда так. Например, Ruby Array # concat docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat . Где можно сильно обжечься, это что-то вроде MyActiveRecordModel.column_names.concat (...). Вместо этого вы должны клонировать его перед выполнением concat.
wintondeshong
15

Знак вопроса означает, что метод возвращает логическое значение. Уже ответили здесь:

Что означает оператор вопросительного знака в Ruby?

Челка означает, что метод воздействует на сам объект. Уже ответили здесь:

Почему в методах Ruby используются восклицательные знаки?

Билл
источник
8

В Ruby это ?означает, что метод вернет логическое значение, а !модифицирует объект, для которого он был вызван. Они нужны для улучшения читабельности при просмотре кода.

Дж. Лундберг
источник
5

В отличие от - я полагаю - большинства языков программирования ...

Ruby, методы могут заканчиваться вопросительными или восклицательными знаками.

По соглашению, методы, которые отвечают на вопросы (например, Array # empty? Возвращает true, если получатель пуст), заканчиваются вопросительными знаками.

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

Источник: http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/ , Раздел Смешные названия методов

мику
источник
1
Также методы, заканчивающиеся на ?, называются методами предиката.
Васим
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 и выбросить.

Вместо этого вы должны клонировать его перед выполнением concat. К счастью, мой тестовый пакет поймал это, но ... внимание!

Wintondeshong
источник