English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
исключения и выполнение всегда связаны друг с другом. Если вы открываете файл, который не существует, и не правильно обрабатываете эту ситуацию, то ваша программа считается низкого качества.
если происходит исключение, то программа останавливается. Исключения используются для обработки различных типов ошибок, которые могут возникнуть в процессе выполнения программы, поэтому необходимо предпринять соответствующие меры, чтобы не остановить программу полностью.
Ruby предоставляет совершенный механизм обработки исключений. Мы можем begin/end в блоке можно добавить код, который может вызвать исключение, и использовать rescue подразделение рассказывает Ruby, какие типы исключений нужно обработать.
begin #开始 raise.. #抛出异常 rescue [ExceptionType = StandardException] #捕获指定类型的异常默认值是 StandardException $! # указывает на информацию об исключении $@ # указывает на положение кода, где возникло исключение else #其余的 исключения .. ensure # неважно, есть ли исключение, вход в этот блок кода end # конец
от begin к rescue всего в блоке. Если в процессе выполнения блока происходит исключение, управление передается rescue и end между
для begin каждый rescue пункт, Ruby сравнивает выброшенное исключение с каждым параметром. Если имя исключения в блоке rescue совпадает с типом текущего выброшенного исключения или является его суперклассом, то происходит успешное совпадение.
Если исключение не соответствует всем指定的 типам ошибок, мы можем использовать все rescue пункт. else пункт.
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue file = STDIN end print file, "==", STDIN, "\n"
Результат выполнения примера выше. Вы можете видеть,STDIN заменяет file поэтомуоткрытиенеудача.
#<IO:0xb7d16f84>==#<IO:0xb7d16f84>
Вы можете использовать rescue Блок перехватывает исключение и затем использует retry Сначала выполняется команда в блоке. begin блок.
begin # Исключение, выброшенное этим кодом, будет перехвачено следующим блоком rescue rescue # Этот блок будет перехватывать все типы исключений retry # Это вернет управление к началу begin end
#!/usr/bin/ruby begin file = open("/unexistant_file") if file puts "File opened successfully" end rescue fname = "existant_file" retry end
Вот процесс обработки:
Произошло исключение при открытии.
Перепрыгнуть к rescue. fname заново присваивается.
С помощью retry перепрыгнуть к началу begin.
В этот раз файл успешно открыт.
Продолжить базовый процесс.
Примечание:Если переназванный файл не существует, этот пример кода будет бесконечно пытаться. Поэтому при обработке исключений будьте осторожны. retry.
Вы можете использовать raise Эта команда выбрасывает исключение. Следующие методы выбрасывают исключение при вызове. Его второе сообщение будет выведено.
raise или raise "Error Message" или raise ExceptionType, "Error Message" или raise ExceptionType, "Error Message" condition
Первый вид просто перебрасывает текущее исключение (если нет текущего исключения, выбрасывается RuntimeError). Это используется в обработчиках исключений, которые необходимо объяснить до передачи исключения.
Второй вид создает новый RuntimeError Исключение, устанавливающее его сообщение как заданную строку. Это исключение затем выбрасывается в呼叫ный стек.
Третий вид создает исключение с использованием первого параметра и устанавливает связанное сообщение как второй параметр.
Четвертый вид ähnlich dem dritten, вы можете добавить любые дополнительные условия (например unless)для выброса исключения.
#!/usr/bin/ruby begin puts 'Я перед raise.' raise 'Произошла ошибка.' puts 'Я после raise.' rescue puts 'Я спасен.' end puts 'Я после блока begin.'
Результат выполнения примера выше:
Я перед raise. Я спасен. Я после блока begin.
еще один пример raise Пример использования:
#!/usr/bin/ruby begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect end
Результат выполнения примера выше:
A test exception. ["main.rb:4"]
Иногда вам нужно обеспечить завершение некоторых операций в конце блока кода, независимо от того, был ли выброшен исключение. Например, если вы открыли файл при входе в блок, при выходе из блока вам нужно убедиться, что файл закрыт.
ensure Условие делает именно это. ensure размещается после последнего rescue и содержит блок кода, который всегда выполняется при завершении блока. Это независимо от того, был ли блок завершен нормально, выброшено и обработано исключение, или он был завершен из-за не捕获ленного исключения.ensure блок всегда выполняется.
begin #.. Процесс #.. Выбрасывает исключение rescue #.. Обработка ошибок ensure #.. В конце убедитесь, что выполняется #.. Это всегда выполняется end
begin raise 'A test exception.' rescue Exception => e puts e.message puts e.backtrace.inspect ensure puts "Обеспечение выполнения" end
Результат выполнения примера выше:
A test exception. ["main.rb:4"] Обеспечение выполнения
если предоставлен else условие, обычно放置 в rescue после условия, в любое время ensure ранее.
else Тело условия выполняется только в том случае, если в теле кода не было выброшено исключение.
begin #.. Процесс #.. Выбрасывает исключение rescue #.. Обработка ошибок else #.. Если нет исключений, выполняется ensure #.. В конце убедитесь, что выполняется #.. Это всегда выполняется end
begin # Выбрасывает 'A test exception.' puts "Я не поднимаю исключение" rescue Exception => e puts e.message puts e.backtrace.inspect else puts "Поздравляем -- нет ошибок!" ensure puts "Обеспечение выполнения" end
Результат выполнения примера выше:
Я не поднимаю исключение Поздравляем -- нет ошибок! Обеспечение выполнения
Использование переменной $! позволяет捕获 сообщение об ошибке, которое было выброшено.
Механизмы raise и rescue позволяют прервать выполнение при возникновении ошибки, иногда необходимо跳出 некоторые глубоко вложенные структуры в процессе нормального обработки. В таких случаях catch и throw становятся полезными.
catch Определен блок, использующий заданное имя (будь то Symbol или String) в качестве тега. Блок выполняется до тех пор, пока не встретится throw.
throw :lablename #.. Это не будет выполнено catch :lablename do #.. После throw выполняется соответствующий catch end или throw :lablename condition #.. Это не будет выполнено catch :lablename do #.. После throw выполняется соответствующий catch end
В следующем примере, если пользователь в ответ на любое提示 вводит '!', используется throw для завершения взаимодействия с пользователем.
def promptAndGet(prompt) print prompt res = readline.chomp throw :quitRequested if res == "!" return res end catch :quitRequested do name = promptAndGet("Name: ") age = promptAndGet("Age: ") sex = promptAndGet("Sex: ") # .. # Обработка информации end promptAndGet("Name:")
Этот программный код требует взаимодействия с пользователем, вы можете попробовать его на своем компьютере. Результат выполнения примера приведен выше:
Имя: Ruby on Rails Возраст: 3 Пол: ! Имя: Just Ruby
Стандартные классы и модули Ruby генерируют исключения. Все классы исключений образуют иерархию, включая верхний класс Exception. На следующем уровне семь различных типов:
Interrupt
NoMemoryError
SignalException
ScriptError
StandardError
SystemExit
Fatal - это еще одно исключение в этом слое, но интерпретатор Ruby использует его только внутренне.
ScriptError и StandardError имеют свои подклассы, но в данном случае нам не нужно знать эти детали. Самое важное - создать свои собственные классы исключений, они должны быть подклассами класса Exception или его потомками.
Давайте посмотрим на пример:
class FileSaveError < StandardError attr_reader :reason def initialize(reason) @reason = reason end end
Теперь посмотрите на следующий пример, который использует上面的 исключение:
File.open(path, "w") do |file| begin # Запись данных... rescue # Ошибка raise FileSaveError.new($!) end end
Здесь最重要ая строка - raise FileSaveError.new($!)Мы вызываем raise, чтобы показать, что ошибка уже произошла, и передаем ее новому примеру FileSaveError, так как данные не могут быть записаны из-за определенной ошибки.