Ruby a deux mécanismes d'exceptions différents: Throw / Catch et Raise / Rescue.
Pourquoi en avons-nous deux?
Quand devriez-vous utiliser l'un et pas l'autre?
Ruby a deux mécanismes d'exceptions différents: Throw / Catch et Raise / Rescue.
Pourquoi en avons-nous deux?
Quand devriez-vous utiliser l'un et pas l'autre?
Réponses:
Je pense que http://hasno.info/ruby-gotchas-and-caveats a une explication décente de la différence:
catch / throw n'est pas la même chose que relancer / sauver. catch / throw vous permet de quitter rapidement les blocs pour revenir à un point où un catch est défini pour un symbole spécifique, le sauvetage de la levée est le vrai traitement des exceptions impliquant l'objet Exception.
raisec'est très cher. thrown'est pas. Pensez throwà utiliser gotopour sortir d'une boucle.
raise, fail, rescueEt ensurepoignée erreurs , également connu sous le nom des exceptionsthrowet catchsont flux de contrôleContrairement à d'autres langages, le throw et le catch de Ruby ne sont pas utilisés pour les exceptions. Au lieu de cela, ils fournissent un moyen de terminer l'exécution plus tôt lorsqu'aucun travail supplémentaire n'est nécessaire. (Grimm, 2011)
Terminer un seul niveau de flux de contrôle, comme une whileboucle, peut être fait avec un simple return. La terminaison de nombreux niveaux de flux de contrôle, comme une boucle imbriquée, peut être effectuée avec throw.
Bien que le mécanisme d'exception de relance et de sauvetage soit idéal pour abandonner l'exécution lorsque les choses tournent mal, il est parfois agréable de pouvoir sortir d'une construction profondément imbriquée pendant le traitement normal. C'est là que la capture et le lancer sont utiles. (Thomas et Hunt, 2001)
https://coderwall.com/p/lhkkug/don-t-confuse-ruby-s-throw-statement-with-raise offre une excellente explication que je doute que je puisse améliorer. Pour résumer, en récupérant quelques exemples de code du billet de blog au fur et à mesure:
raise/ rescuesont les analogues les plus proches de la construction throw/ catchque vous connaissez d'autres langages (ou de raise/ de Python except). Si vous avez rencontré une condition d'erreur et que vous la surmonteriez throwdans une autre langue, vous devriez raiseen Ruby.
Ruby throw/ catchvous permet d'interrompre l'exécution et de monter dans la pile à la recherche d'un catch(comme raise/ rescuefait), mais n'est pas vraiment destiné aux conditions d'erreur. Il devrait être utilisé rarement, et est là uniquement lorsque le catchcomportement «remonter la pile jusqu'à ce que vous trouviez un correspondant » a du sens pour un algorithme que vous écrivez, mais cela n'aurait pas de sens de penser que le throwcomme correspondant à une erreur état.
À quoi sert le catch and throw dans Ruby? propose quelques suggestions sur les bonnes utilisations de throw/ catchconstruct.
Les différences de comportement concrètes entre eux comprennent:
rescue Foosauvera des instances d' Fooinclusion de sous-classes de Foo. catch(foo)ne fonctionnera que pour le même objet,Foo . Non seulement vous ne pouvez pas passer catchun nom de classe pour en attraper des instances, mais cela ne fera même pas de comparaisons d'égalité. Par exemple
catch("foo") do
throw "foo"
end
vous donnera une UncaughtThrowError: uncaught throw "foo"(ou une ArgumentErrorversion in de Ruby antérieure à 2.2)
Plusieurs clauses de sauvetage peuvent être répertoriées ...
begin
do_something_error_prone
rescue AParticularKindOfError
# Insert heroism here.
rescue
write_to_error_log
raise
end
alors que plusieurs catches doivent être imbriquées ...
catch :foo do
catch :bar do
do_something_that_can_throw_foo_or_bar
end
endUn nu rescueéquivaut à rescue StandardErroret est une construction idiomatique. Un "nu catch", comme catch() {throw :foo}, n'attrapera jamais rien et ne devrait pas être utilisé.
gotoen C / C ++ comme @docwhat a mentionné, Java a marqué break et continue . (Python a également une proposition rejetée pour cela.)