Яка різниця між "підвищити" foo "" і "підвищити Exception.new (" foo ")"?


Відповіді:


121

Технічно перший піднімає RuntimeError із встановленим повідомленням "foo", а другий викликає виняток із повідомленням, встановленим на "foo".

Практично існує значна різниця між тим, коли ви хочете використовувати перше, і коли ви хочете використовувати друге.

Простіше кажучи, ви, мабуть, хочете RuntimeErrorне Exception. Рятувальний блок без аргументу застане RuntimeErrors, але НЕ вловлює Exceptions. Тож якщо ви піднімете Exceptionсвій код, цей код не зачепить його:

begin
rescue
end

Для того, щоб зловити Exceptionвас, вам доведеться зробити це:

begin
rescue Exception
end

Це означає, що в деякому сенсі Exceptionпомилка "гірше", ніж a RuntimeError, тому що вам доведеться зробити більше роботи, щоб відновити її.

Отже, чого ви хочете, залежить від того, як ваш проект виконує обробку помилок. Наприклад, у наших демонах головний цикл містить порожній рятувальний рятувальний пристрій, який буде вловлювати RuntimeErrors, повідомляти про них, а потім продовжувати. Але за однієї чи двох обставин ми хочемо, щоб демон справді помер насправді від помилки, і в такому випадку ми піднімаємо ангіну Exception, яка йде прямо через наш «звичайний код обробки помилок» і виходить.

І знову: якщо ви пишете код бібліотеки, ви, мабуть, хочете а RuntimeError, а не Exception, оскільки користувачі вашої бібліотеки будуть здивовані, якщо вони виявлять помилки, які порожній rescueблок не може наздогнати, і знадобиться їм хвилина, щоб зрозуміти, чому.

Нарешті, я повинен сказати, що RuntimeErrorце підклас StandardErrorкласу, і власне правило полягає в тому, що, хоча ви можете raise будь-який тип об'єктів, пустий rescueза замовчуванням буде тільки ловити все, що успадковується StandardError. Все інше повинно бути конкретним.


2
дуже інформативно, дякую. кілька речей: [1] Цей останній абзац був найяскравішим, і дозвольте мені відкрити в irb те, про що ви не згадували: RuntimeError < StandardError < Exception[2] отже, цей другий блок коду охопить і виняток, і RuntimeError [3] цікаво / дивно, що "голі" підйоми та порятунки трапляються працювати саме з цим винятком [4], можливо, головним правилом є підвищення RuntimeError до клієнтського коду, але підняття та врятування власних спеціальних винятків всередині власного коду?
Джон Бачір

1
[1, 2] Так. [3] не впевнений ... [4] Коли я кодую у своїх найпрофесійніших, я схильний створювати власні типи помилок, які успадковуються від StandardError. Це не повинно бути складнішим, ніж декілька рядків class MissingArgumentsError < StandardError; end.
Даніель Люкрафт

Дуже інформативно, але в яких ситуаціях ви хочете викинути Виняток, а не помилку часу запуску, якщо помилка часу запуску є кращою для написання бібліотеки?
Чіхунг Ю

35

З офіційної документації:

raise   
raise( string )
raise( exception [, string [, array ] ] )

Без аргументів, збільшує виняток у $!або піднімає, RuntimeErrorякщо $!є нульовим. За допомогою одного Stringаргументу він піднімає a RuntimeErrorз рядком як повідомлення. В іншому випадку першим параметром має бути назва Exceptionкласу (або об'єкта, який повертає Exceptionвиняток при надсиланні). Необов'язковий другий параметр встановлює повідомлення, пов'язане з винятком, а третій параметр є масивом інформації про зворотний виклик. Винятки становлять рятувальний пункт begin...endблоків.

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