Ruby Exceptions - Почему "еще"?
Я пытаюсь понять исключения в Ruby, но я немного смущен. Учебное пособие, которое я использую, говорит, что если возникает исключение, которое не соответствует ни одному из исключений, идентифицированных операциями спасения, вы можете использовать "else", чтобы поймать его:
begin
# -
rescue OneTypeOfException
# -
rescue AnotherTypeOfException
# -
else
# Other exceptions
ensure
# Always will be executed
end
Тем не менее, я также видел позже в учебнике "Спасение", которое используется без указанного исключения:
begin
file = open("/unexistant_file")
if file
puts "File opened successfully"
end
rescue
file = STDIN
end
print file, "==", STDIN, "\n"
Если вы можете это сделать, тогда мне нужно использовать еще? Или я могу просто использовать общее спасение в конце, как это?
begin
# -
rescue OneTypeOfException
# -
rescue AnotherTypeOfException
# -
rescue
# Other exceptions
ensure
# Always will be executed
end
Ответы
Ответ 1
else
- это когда блок завершается без исключения. Выполняется запуск ensure
, завершится ли блок успешно или нет. Пример:
begin
puts "Hello, world!"
rescue
puts "rescue"
else
puts "else"
ensure
puts "ensure"
end
Это напечатает Hello, world!
, затем else
, затем ensure
.
Ответ 2
Здесь конкретный прецедент для else
в выражении begin
. Предположим, вы пишете автоматические тесты, и вы хотите написать метод, который возвращает ошибку, вызванную блоком. Но вы также хотите, чтобы тест завершился неудачей, если блок не вызвал ошибку. Вы можете сделать это:
def get_error_from(&block)
begin
block.call
rescue => err
err # we want to return this
else
raise "No error was raised"
end
end
Обратите внимание, что вы не можете переместить raise
внутри блока begin
, потому что он получит rescue
d. Конечно, есть другие способы, не используя else
, например, проверить, <<27 > nil
после end
, но это не так лаконично.
Лично я редко использую else
таким образом, потому что я думаю, что он редко нужен, но он очень пригодится в этих редких случаях.
Ответ 3
Блок else
в начальном блоке начала восстановления используется, когда вы, возможно, ожидаете, что произойдет какое-то исключение. Если вы выполняете все ожидаемые исключения, но по-прежнему ничего не поднимаете, то в своем блоке else вы можете делать все, что нужно сейчас, когда вы знаете, что ваш исходный код бежал без ошибок.
Ответ 4
Единственная причина, по которой я могу наблюдать за блоком else
, - это если вы хотите выполнить что-то перед блоком ensure
, когда код в блоке begin
не вызвал никаких ошибок.
begin
puts "Hello"
rescue
puts "Error"
else
puts "Success"
ensure
puts "my old friend"
puts "I've come to talk with you again."
end
Ответ 5
Благодаря else
вы иногда можете объединить два вложенных блока begin end
.
Итак (упрощенный пример из моего текущего кода) вместо:
begin
html = begin
NetHTTPUtils.request_data url
rescue NetHTTPUtils::Error => e
raise unless 503 == e.code
sleep 60
retry
end
redo unless html["market"]
end
вы пишете:
begin
html = NetHTTPUtils.request_data url
rescue NetHTTPUtils::Error => e
raise unless 503 == e.code
sleep 60
retry
else
redo unless html["market"]
end