📜  Ruby异常

📅  最后修改于: 2021-01-08 13:18:20             🧑  作者: Mango

Ruby异常

Ruby异常是一个对象,Exception类的实例或该类的后代。它代表一些特殊情况。

在Ruby程序中,当出现问题时,它将引发异常行为。默认情况下,Ruby程序在引发异常时终止。

我们可以在Ruby中声明一些异常处理程序。异常处理程序是一个代码块,当其他代码块中发生异常时,将执行该代码。

异常以两种方式处理。您可以终止程序或处理异常。要处理异常,可以提供一个救援条款。通过提供此选项,程序控制将流到救援子句。

当引发异常但未处理异常时,全局变量$!包含当前异常, $ @包含当前异常的回溯。

Ruby预定义的类(例如Exception及其子类)可帮助您处理程序错误。在Ruby异常层次结构中,大多数子类都扩展了StandardError类。这些是正常的例外。

Ruby类异常

内置的异常子类如下:

  • NoMemoryError
  • ScriptError
  • 安全错误
  • SignalException
  • 标准错误
  • SystenExit
  • SystemStackError
  • 致命-无法挽救

例:

def raise_exception   
  puts 'I am before the raise.'   
  raise 'oops! An error has occured'   
  puts 'I am after the raise'   
end   
raise_exception  

输出:

提高方法来自内核模块。

处理异常

为了处理异常,引发异常的代码包含在begin-end块内。使用救援子句,我们可以声明我们要处理的异常类型。

例:

def raise_and_rescue   
  begin   
    puts 'Before the raise.'   
    raise 'An error occured.'   
    puts 'After the raise.'   
  rescue   
    puts 'Code rescued.'   
  end   
  puts 'After the begin block.'   
end   
raise_and_rescue  

输出:

在上面的示例中,中断的代码无法完全运行。在异常之后,处理代码在begin-end块之后恢复。

如果在挽救子句中未定义任何参数,则该参数默认为StandardError。每个救援子句都指定了多个要捕获的异常。如果使用不带任何参数的raise,可能会重新引发异常。

救援条款写在开始/救援块中。如果一个救援条款未处理例外,则将与下一个一起处理。

    begin
code..
rescue OneTypeOfException
code..
rescue AnotherTypeOfException
 code..
else
  # Other exceptions
end

在begin块中,每个带有引发异常的营救条款将依次与每个参数进行比较。当抛出的错误的类型与抢救子句中命名的异常相同或是该异常的超类时,它将匹配。如果begin语句的主体无例外地完成,则执行else子句。如果发生异常,则将不执行else子句。

异常对象

异常对象是普通对象。可以将抢救的异常保留在抢救子句中的变量中。

例:

begin 
  raise 'an exception' 
rescue ZeroDivisionError => e 
  puts "Exception Class: #{ e.class.name }" 
  puts "Exception Message: #{ e.message }" 
  puts "Exception Backtrace: #{ e.backtrace }" 
end 

Exception类定义了两个方法,这些方法返回有关异常的详细信息。 message方法返回定义错误说明的字符串。 backtrace方法返回一个字符串数组,该数组表示引发异常时的调用堆栈。

使用重试语句

通常,在救援子句中,捕获异常,并在begin块之后恢复代码。使用retry语句,可以在捕获异常后从头开始恢复救援块代码。

句法:

begin
   code....
rescue
    # capture exceptions
    retry  # program will run from the begin block
end

例:

#!/usr/bin/ruby 

begin 
   x = Dir.mkdir "alreadyExist" 
   if x 
      puts "Directory created" 
   end 
rescue 
   y = "newDir" 
   retry 
end 

上面的程序运行如下:

步骤1在begin块中,编写代码以创建一个已经存在的目录。

步骤2这将引发错误。

步骤3在救援区中,y被重新分配。

步骤4 retry语句将转到begin块。

步骤5将创建目录。

使用凸起语句

引发语句用于引发异常。

句法:

raise 

要么,

raise "Error Message" 

要么,

raise ExceptionType, "Error Message"

要么,

raise ExceptionType, "Error Message" condition

第一个重新引发当前异常。它用于异常处理程序,在异常处理程序中,异常在传递之前被拦截。

第二个创建新的RuntimeError异常。然后在调用堆栈中引发此异常。

第三个使用第一个参数创建异常,然后将关联的消息设置为第二个参数。

第四个类似于第三个。在此,您可以添加任何条件语句以引发异常。

例:

#!/usr/bin/ruby 

begin   
    puts 'code before raise.'   
    raise 'exception occurred.'   
    puts 'code after raise.'   
rescue   
    puts 'I am rescued.'   
end   
puts 'code after begin block.'  

输出:

使用保证声明

有一个保证子句,保证在代码末尾进行某些处理。无论是否引发异常,sure块始终运行。它被放置在最后一个救援子句之后,并且将在块终止时始终执行。

在任何情况下,无论发生异常,抢救异常还是未捕获的异常终止代码,sure块都将运行。

句法:

begin 
  code..
   #..raise exception
rescue 
   #.. exception is rescued
ensure 
   #.. This code will always execute.
end

例:

begin 
  raise 'Exception' 
rescue Exception => e 
  puts e.message 
  puts e.backtrace.inspect 
ensure 
  puts "The ensure code will always run" 
end

输出:

使用else语句

else子句始终出现在救援子句之后和确保子句之前。如果没有引发异常,则仅执行else块。

句法:

begin 
   code.. 
   #..raise exception
rescue 
   # .. exception is rescued
else
   #.. executes if there is no exception
ensure 
   #..  This code will always execute.
end

例:

begin 
 # raise 'A test exception.' 
 puts "no exception is raised" 
rescue Exception => e 
  puts e.message 
  puts e.backtrace.inspect 
else 
   puts "else code will be executed as no exception is raised." 
ensure 
  puts "ensure code will run" 
end

输出:

红宝石抓住和扔

当代码中不需要进一步的工作时,Ruby的catch and throw提供了一种从执行中跳出的方法。

catch定义了一个标有给定名称的块。它用于跳出嵌套代码。使用catch,该块将正常执行,直到遇到throw。

捕捉和抛出方法比救援和引发子句更快。因此,它更适合使用。

句法:

throw :lablename
#.. this  code will not be executed
catch :lablename do
#.. matching catch will be executed after a throw is encountered.
end

要么,

throw :lablename condition
#.. this code will not be executed
catch :lablename do
#.. matching catch will be executed after a throw is encountered.
end

例:

def promptAndGet(prompt) 
   print prompt 
   res = readline.chomp 
   throw :quitRequested if res == "!" 
   return res 
end 

catch :quitRequested do 
   name = promptAndGet("Name: ") 
   age = promptAndGet("Occupation: ") 
   # .. 
   # process information 
end 
promptAndGet("Name:")

输出: