Qual é o propósito de “!” e “?” no final dos nomes dos métodos?

Respostas:

160

É "apenas adoçar" para facilitar a leitura, mas eles têm significados comuns:

  • Os métodos que terminam em !realizam alguma mudança permanente ou potencialmente perigosa ; por exemplo:
    • Enumerable#sortretorna uma versão classificada do objeto enquanto o Enumerable#sort!classifica no lugar.
    • No Rails, ActiveRecord::Base#saveretorna falso se o salvamento falhar, enquanto ActiveRecord::Base#save!gera uma exceção.
    • Kernel::exitfaz com que um script saia, enquanto o Kernel::exit!faz imediatamente, ignorando quaisquer manipuladores de saída.
  • Os métodos que terminam em ?retornar um booleano , o que faz o código fluir ainda mais intuitivamente como uma frase - if number.zero?parece "se o número for zero", mas if number.zeroparece estranho.

Em seu exemplo, name.reverseavalia como uma string invertida, mas somente após a name.reverse!linha a namevariável realmente contém o nome invertido. name.is_binary_data?parece "são namedados binários?".

jtbandes
fonte
22
Uma observação importante é que você só deve ter um método bang se também tiver um método não bang correspondente. O estrondo é usado para distinguir a versão "mais surpreendente" do método da "menos surpreendente". Se você tiver apenas um método, não há necessidade de fazer distinção e não deve nomeá-lo com estrondo. Veja Array#clear, por exemplo. Ele limpa a matriz. Limpar a matriz altera-a naturalmente. Não há nada de surpreendente nisso, o nome já deixa claro, portanto: sem estrondo. Consulte ruby-forum.com/topic/176830#773946 .
Jörg W Mittag
2
Adicionando ao que @ JörgWMittag declarou, de acordo com o Guia de Estilo Ruby : Os nomes de métodos potencialmente perigosos (ou seja, métodos que modificam a si mesmo ou os argumentos, exit! (Não executa os finalizadores como o exit faz), etc.) devem terminar com um ponto de exclamação se houver uma versão segura desse método perigoso .
Tod Birdsall
2
Cuidado, nem sempre é esse o caso. Por exemplo, Ruby Array # concat docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat . Onde você pode se queimar gravemente é algo como MyActiveRecordModel.column_names.concat (...). Em vez disso, você deve cloná-lo antes de fazer o concat.
wintondeshong
8

Em Ruby, ?significa que o método irá retornar um booleano e !modificar o objeto no qual foi chamado. Eles existem para melhorar a legibilidade ao examinar o código.

J Lundberg
fonte
5

Em contraste com a - suponho - maioria das linguagens de programação ...

Ruby, os métodos podem terminar com pontos de interrogação ou exclamação.

Por convenção, os métodos que respondem às perguntas (ou seja, Array # empty? Retorna true se o receptor estiver vazio) terminam em pontos de interrogação.

Métodos potencialmente “perigosos” (isto é, métodos que modificam a si mesmo ou os argumentos, saída! Etc.) por convenção terminam com pontos de exclamação.

De: http://www.ruby-lang.org/en/documentation/ruby-from-other-languages/ , Section Funny method names

Miku
fonte
1
Além disso, os métodos que terminam com ?são chamados de métodos de predicado.
Waseem
1

Cuidado, nem sempre é esse o caso. Veja, por exemplo, Ruby Array # concat http://docs.ruby-lang.org/en/2.0.0/Array.html#method-i-concat .

Onde você pode se queimar seriamente é algo como MyActiveRecordModel.column_names.concat([url]) . Chamadas posteriores relacionadas a MyActiveRecordModel tentarão procurar uma coluna de 'url' para MyActiveRecordModel e lançar.

Em vez disso, você deve cloná-lo antes de fazer o concat. Felizmente meu conjunto de testes pegou esse, mas ... atenção!

Wintondeshong
fonte