В чем разница - техническая, философская, концептуальная или иная - между
raise "foo"
и
raise Exception.new("foo")
?
В чем разница - техническая, философская, концептуальная или иная - между
raise "foo"
и
raise Exception.new("foo")
?
Ответы:
Технически, первый вызывает RuntimeError с сообщением, установленным в "foo", а второй вызывает Exception с сообщением, установленным в "foo".
На практике существует значительная разница между тем, когда вы хотите использовать первое и когда вы хотите использовать второе.
Проще говоря, вы, вероятно, хотите, чтобы RuntimeErrorне был Exception. Спасательный блок без аргументов будет ловить RuntimeErrors, но НЕ ловит Exceptions. Поэтому, если вы поднимете 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 в клиентский код, но поднять и спасти свои собственные исключения внутри собственного кода?