В чем разница - техническая, философская, концептуальная или иная - между
raise "foo"
и
raise Exception.new("foo")
?
В чем разница - техническая, философская, концептуальная или иная - между
raise "foo"
и
raise Exception.new("foo")
?
Ответы:
Технически, первый вызывает RuntimeError с сообщением, установленным в "foo"
, а второй вызывает Exception с сообщением, установленным в "foo"
.
На практике существует значительная разница между тем, когда вы хотите использовать первое и когда вы хотите использовать второе.
Проще говоря, вы, вероятно, хотите, чтобы RuntimeError
не был Exception
. Спасательный блок без аргументов будет ловить RuntimeErrors
, но НЕ ловит Exception
s. Поэтому, если вы поднимете Exception
в своем коде, этот код его не поймает:
begin
rescue
end
Чтобы поймать, Exception
вам нужно будет сделать следующее:
begin
rescue Exception
end
Это означает, что в каком-то смысле Exception
ошибка «хуже», чем ошибка RuntimeError
, потому что вам нужно проделать больше работы, чтобы исправить ее.
То, что вы хотите, зависит от того, как ваш проект обрабатывает ошибки. Например, в наших демонах в основном цикле есть пустое спасение, которое перехватит их RuntimeErrors
, сообщит о них и затем продолжит. Но в одном или двух случаях мы хотим, чтобы демон действительно умер из-за ошибки, и в этом случае мы вызываем Exception
, который проходит через наш «нормальный код обработки ошибок» и удаляется.
И снова, если вы пишете код библиотеки, вы, вероятно, захотите a RuntimeError
, а не a Exception
, поскольку пользователи вашей библиотеки будут удивлены, если она вызовет ошибки, которые rescue
не может уловить пустой блок, и им потребуется некоторое время, чтобы понять, почему.
Наконец, я должен сказать, что RuntimeError
это подкласс StandardError
класса, и фактическое правило заключается в том, что, хотя вы можете использовать raise
любой тип объекта, пустое поле rescue
по умолчанию будет перехватывать только все, что наследуется от StandardError
. Все остальное должно быть конкретным.
StandardError
. Это не должно быть сложнее, чем несколько строк вроде class MissingArgumentsError < StandardError; end
.
raise
raise( string )
raise( exception [, string [, array ] ] )
Без аргументов вызывает исключение $!
или RuntimeError
если $!
равно nil. С одним String
аргументом он вызывает RuntimeError
строку как сообщение. В противном случае первым параметром должно быть имя Exception
класса (или объекта, который возвращает Exception
исключение при отправке). Необязательный второй параметр устанавливает сообщение, связанное с исключением, а третий параметр представляет собой массив информации обратного вызова. Исключения улавливаются условием восстановления begin...end
блоков.
raise "Failed to create socket"
raise ArgumentError, "No parameters", caller
RuntimeError < StandardError < Exception
[2] таким образом, что второй блок кода будет поймать как исключение и RuntimeError [3] интересно / странно, что «голый» подъем и спасение работают с этим конкретным исключением [4], возможно, практическое правило состоит в том, чтобы вызвать RuntimeError в клиентский код, но поднять и спасти свои собственные исключения внутри собственного кода?