红宝石 |例外
一个好的程序(或程序员)可以预测错误并安排以有效的方式处理它们。这并不像听起来那么容易。异常是在运行时发生的错误。它停止程序的执行。它们是由各种各样的异常情况引起的,例如内存不足、无法打开文件、试图将对象初始化为不可能的值等。
什么是例外?
异常是在程序执行期间(即在运行时)发生的不希望的或意外事件,它破坏了程序指令的正常流程。
错误与异常
错误:
- 错误是计算机程序执行过程中可能出现的意外问题。
- 无法处理错误。
- 所有错误都是例外。
例外:
- 异常是运行时可能出现的意外事件。
- 可以使用 try-catch 机制处理异常。
- 所有异常都不是错误。
处理异常的传统方法
处理异常的传统方法包括使用返回码。 open 方法返回一些特定的值并说它失败了。然后这个值被传回调用例程的层,直到有人想要对它负责。这种方法的问题是管理所有这些错误非常复杂。如果一个方法调用 open、read 并最后调用 close,那么每个方法都有可能返回错误指示。现在,函数将如何区分返回给调用者的值中的这些错误代码。
这里的异常类为这个问题提供了解决方案。异常类向程序或程序员提供有关将错误放入对象的封装信息。异常对象发送回调用堆栈,直到系统找到知道如何处理发生的错误的合适代码。
异常类及其层次结构
它是包含对象中异常信息的包。 Ruby 包含一个预定义的异常层次结构,如下所示:
在上图中,大多数异常都属于StandardError 类,这是 Ruby 程序中出现的一般异常。其余的异常描述了更严重、更低级别和更难恢复的情况,Ruby 程序不会尝试处理它们。当用户想要创建异常时,他可以使用内置异常类之一。在 Ruby 中,用户也可以创建自己的异常,但为此,他必须将该异常设为StandardError的子类或其子类之一。如果他没有在StandardError中定义,则默认情况下不会捕获异常。每个异常都包含消息字符串和堆栈回溯。因此,如果用户定义了自己的异常,那么他必须在其中添加此信息。
例子:
# Ruby program to illustrate the exception
# taking two integer value
$A = 14;
$B = 0;
# divide by zero error
$C = $A / $B;
puts "The Result is: #{$C}"
运行时错误:
source_file.rb:10:in `/’: divided by 0 (ZeroDivisionError)
from source_file.rb:10:in `
解释:在上面的程序中,用户试图将 14 除以 0。所以这里 Ruby 编译器会抛出一个异常ZeroDivisionError 。
创建用户定义的异常: Ruby 使用称为raise的内核方法来创建异常,这些异常将是 Exception 类或其子类之一的实例。 rescue子句用于处理 raise 创建的异常。
例子:
# Ruby program to create the user defined exception
# defining a method
def raise_exception
puts 'This is Before Exception Arise!'
# using raise to create exception
raise 'Exception Created'
puts 'This is After Exception Arise -- Not Displayed'
end
# Calling the method
raise_exception
输出:
This is Before Exception Arise!
source_file.rb:9:in `raise_exception': Exception Created (RuntimeError)
from source_file.rb:15:in `'
上述示例代码的解决方案:
# Ruby program to create the user
# defined exception and rescued
# defining a method
def raise_and_rescue
begin
puts 'This is Before Exception Arise!'
# using raise to create an exception
raise 'Exception Created!'
puts 'After Exception'
# using Rescue method
rescue
puts 'Finally Saved!'
end
puts 'Outside from Begin Block!'
end
# calling method
raise_and_rescue
输出:
This is Before Exception Arise!
Finally Saved!
Outside from Begin Block!
解释:在上面的例子中,异常是由 raise 方法引发的(raise 方法直接来自内核模块),代码由于异常的存在而被中断。现在,这个异常由rescue 子句处理,并且程序流在rescue 子句之后继续没有错误。如果程序包含多个救援子句,那么如果第一个救援代码无法处理异常,则下一个救援子句将处理异常。