Яка різниця - технічна, філософська, концептуальна чи інше - між ними
raise "foo"
і
raise Exception.new("foo")
?
Яка різниця - технічна, філософська, концептуальна чи інше - між ними
raise "foo"
і
raise Exception.new("foo")
?
Відповіді:
Технічно перший піднімає RuntimeError із встановленим повідомленням "foo"
, а другий викликає виняток із повідомленням, встановленим на "foo"
.
Практично існує значна різниця між тим, коли ви хочете використовувати перше, і коли ви хочете використовувати друге.
Простіше кажучи, ви, мабуть, хочете RuntimeError
не Exception
. Рятувальний блок без аргументу застане RuntimeErrors
, але НЕ вловлює Exception
s. Тож якщо ви піднімете Exception
свій код, цей код не зачепить його:
begin
rescue
end
Для того, щоб зловити Exception
вас, вам доведеться зробити це:
begin
rescue Exception
end
Це означає, що в деякому сенсі Exception
помилка "гірше", ніж a RuntimeError
, тому що вам доведеться зробити більше роботи, щоб відновити її.
Отже, чого ви хочете, залежить від того, як ваш проект виконує обробку помилок. Наприклад, у наших демонах головний цикл містить порожній рятувальний рятувальний пристрій, який буде вловлювати RuntimeErrors
, повідомляти про них, а потім продовжувати. Але за однієї чи двох обставин ми хочемо, щоб демон справді помер насправді від помилки, і в такому випадку ми піднімаємо ангіну Exception
, яка йде прямо через наш «звичайний код обробки помилок» і виходить.
І знову: якщо ви пишете код бібліотеки, ви, мабуть, хочете а RuntimeError
, а не Exception
, оскільки користувачі вашої бібліотеки будуть здивовані, якщо вони виявлять помилки, які порожній rescue
блок не може наздогнати, і знадобиться їм хвилина, щоб зрозуміти, чому.
Нарешті, я повинен сказати, що RuntimeError
це підклас StandardError
класу, і власне правило полягає в тому, що, хоча ви можете raise
будь-який тип об'єктів, пустий rescue
за замовчуванням буде тільки ловити все, що успадковується StandardError
. Все інше повинно бути конкретним.
StandardError
. Це не повинно бути складнішим, ніж декілька рядків class MissingArgumentsError < StandardError; end
.
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
RuntimeError < StandardError < Exception
[2] отже, цей другий блок коду охопить і виняток, і RuntimeError [3] цікаво / дивно, що "голі" підйоми та порятунки трапляються працювати саме з цим винятком [4], можливо, головним правилом є підвищення RuntimeError до клієнтського коду, але підняття та врятування власних спеціальних винятків всередині власного коду?