主頁(yè) > 知識(shí)庫(kù) > 詳解Ruby中的異常

詳解Ruby中的異常

熱門標(biāo)簽:巫師3地圖標(biāo)注魔力之所 柯城手機(jī)地圖如何做地圖標(biāo)注 淮安自動(dòng)外呼系統(tǒng)供應(yīng)商 AI電銷機(jī)器人 線路 天津外呼系統(tǒng)怎么收費(fèi) 外呼線路從哪里出來(lái)的 漯河電銷 征服者企業(yè)地圖標(biāo)注 中牟外呼系統(tǒng)違法嗎

異常和執(zhí)行總是被聯(lián)系在一起。如果您打開(kāi)一個(gè)不存在的文件,且沒(méi)有恰當(dāng)?shù)靥幚磉@種情況,那么您的程序則被認(rèn)為是低質(zhì)量的。

如果異常發(fā)生,則程序停止。異常用于處理各種類型的錯(cuò)誤,這些錯(cuò)誤可能在程序執(zhí)行期間發(fā)生,所以要采取適當(dāng)?shù)男袆?dòng),而不至于讓程序完全停止。

Ruby 提供了一個(gè)完美的處理異常的機(jī)制。我們可以在 begin/end 塊中附上可能拋出異常的代碼,并使用 rescue 子句告訴 Ruby 完美要處理的異常類型。
語(yǔ)法

begin 
# - 
rescue OneTypeOfException 
# - 
rescue AnotherTypeOfException 
# - 
else 
# 其他異常
ensure
# 總是被執(zhí)行
end

從 begin 到 rescue 中的一切是受保護(hù)的。如果代碼塊執(zhí)行期間發(fā)生了異常,控制會(huì)傳到 rescue 和 end 之間的塊。

對(duì)于 begin 塊中的每個(gè) rescue 子句,Ruby 把拋出的異常與每個(gè)參數(shù)進(jìn)行輪流比較。如果 rescue 子句中命名的異常與當(dāng)前拋出的異常類型相同,或者是該異常的父類,則匹配成功。

如果異常不匹配所有指定的錯(cuò)誤類型,我們可以在所有的 rescue 子句后使用一個(gè) else 子句。
實(shí)例

#!/usr/bin/ruby
 
begin
  file = open("/unexistant_file")
  if file
   puts "File opened successfully"
  end
rescue
   file = STDIN
end
print file, "==", STDIN, "\n"

這將產(chǎn)生以下結(jié)果。您可以看到,STDIN 取代了 file ,因?yàn)榇蜷_(kāi)失敗。
#IO:0xb7d16f84>==#IO:0xb7d16f84>
使用 retry 語(yǔ)句

您可以使用 rescue 塊捕獲異常,然后使用 retry 語(yǔ)句從開(kāi)頭開(kāi)始執(zhí)行 begin 塊。
語(yǔ)法

begin
  # 這段代碼拋出的異常將被下面的 rescue 子句捕獲
rescue
  # 這個(gè)塊將捕獲所有類型的異常
  retry # 這將把控制移到 begin 的開(kāi)頭
end
實(shí)例
#!/usr/bin/ruby
 
begin
  file = open("/unexistant_file")
  if file
   puts "File opened successfully"
  end
rescue
  fname = "existant_file"
  retry
end

以下是處理流程:

  1.     打開(kāi)時(shí)發(fā)生異常。
  2.     跳到 rescue。fname 被重新賦值。
  3.     通過(guò) retry 跳到 begin 的開(kāi)頭。
  4.     這次文件成功打開(kāi)。
  5.     繼續(xù)基本的過(guò)程。

注意:如果被重新命名的文件不存在,本勢(shì)力代碼會(huì)無(wú)限嘗試。所以異常處理時(shí),謹(jǐn)慎使用 retry。
使用 raise 語(yǔ)句

您可以使用 raise 語(yǔ)句拋出異常。下面的方法在調(diào)用時(shí)拋出異常。它的第二個(gè)消息將被輸出。
語(yǔ)法

raise
 
OR
 
raise "Error Message"
 
OR
 
raise ExceptionType, "Error Message"
 
OR
 
raise ExceptionType, "Error Message" condition

第一種形式簡(jiǎn)單地重新拋出當(dāng)前異常(如果沒(méi)有當(dāng)前異常則拋出一個(gè) RuntimeError)。這用在傳入異常之前需要解釋異常的異常處理程序中。

第二種形式創(chuàng)建一個(gè)新的 RuntimeError 異常,設(shè)置它的消息為給定的字符串。該異常之后拋出到調(diào)用堆棧。

第三種形式使用第一個(gè)參數(shù)創(chuàng)建一個(gè)異常,然后設(shè)置相關(guān)的消息為第二個(gè)參數(shù)。

第四種形式與第三種形式類似,您可以添加任何額外的條件語(yǔ)句(比如 unless)來(lái)拋出異常。
實(shí)例

#!/usr/bin/ruby
 
begin 
  puts 'I am before the raise.' 
  raise 'An error has occurred.' 
  puts 'I am after the raise.' 
rescue 
  puts 'I am rescued.' 
end 
puts 'I am after the begin block.' 

這將產(chǎn)生以下結(jié)果:

I am before the raise. 
I am rescued. 
I am after the begin block. 

另一個(gè)演示 raise 用法的實(shí)例:

#!/usr/bin/ruby
 
begin 
 raise 'A test exception.' 
rescue Exception => e 
 puts e.message 
 puts e.backtrace.inspect 
end 

這將產(chǎn)生以下結(jié)果:

A test exception.
["main.rb:4"]

使用 ensure 語(yǔ)句

有時(shí)候,無(wú)論是否拋出異常,您需要保證一些處理在代碼塊結(jié)束時(shí)完成。例如,您可能在進(jìn)入時(shí)打開(kāi)了一個(gè)文件,當(dāng)您退出塊時(shí),您需要確保關(guān)閉文件。

ensure 子句做的就是這個(gè)。ensure 放在最后一個(gè) rescue 子句后,并包含一個(gè)塊終止時(shí)總是執(zhí)行的代碼塊。它與塊是否正常退出、是否拋出并處理異常、是否因一個(gè)未捕獲的異常而終止,這些都沒(méi)關(guān)系,ensure 塊始終都會(huì)運(yùn)行。
語(yǔ)法

begin
  #.. 過(guò)程
  #.. 拋出異常
rescue
  #.. 處理錯(cuò)誤
ensure
  #.. 最后確保執(zhí)行
  #.. 這總是會(huì)執(zhí)行
end
實(shí)例
begin
 raise 'A test exception.'
rescue Exception => e
 puts e.message
 puts e.backtrace.inspect
ensure
 puts "Ensuring execution"
end

這將產(chǎn)生以下結(jié)果:

A test exception.
["main.rb:4"]
Ensuring execution

使用 else 語(yǔ)句

如果提供了 else 子句,它一般是放置在 rescue 子句之后,任意 ensure 之前。

else 子句的主體只有在代碼主體沒(méi)有拋出異常時(shí)執(zhí)行。
語(yǔ)法

begin
  #.. 過(guò)程
  #.. 拋出異常
rescue
  #.. 處理錯(cuò)誤
else
  #.. 如果沒(méi)有異常則執(zhí)行
ensure
  #.. 最后確保執(zhí)行
  #.. 這總是會(huì)執(zhí)行
end
實(shí)例
begin
 # 拋出 'A test exception.'
 puts "I'm not raising exception"
rescue Exception => e
 puts e.message
 puts e.backtrace.inspect
else
  puts "Congratulations-- no errors!"
ensure
 puts "Ensuring execution"
end

這將產(chǎn)生以下結(jié)果:

I'm not raising exception
Congratulations-- no errors!
Ensuring execution

使用 $! 變量可以捕獲拋出的錯(cuò)誤消息。
Catch 和 Throw

raise 和 rescue 的異常機(jī)制能在發(fā)生錯(cuò)誤時(shí)放棄執(zhí)行,有時(shí)候需要在正常處理時(shí)跳出一些深層嵌套的結(jié)構(gòu)。此時(shí) catch 和 throw 就派上用場(chǎng)了。

catch 定義了一個(gè)使用給定的名稱(可以是 Symbol 或 String)作為標(biāo)簽的塊。塊會(huì)正常執(zhí)行知道遇到一個(gè) throw。
語(yǔ)法

throw :lablename
#.. 這不會(huì)被執(zhí)行
catch :lablename do
#.. 在遇到一個(gè) throw 后匹配將被執(zhí)行的 catch
end
 
OR
 
throw :lablename condition
#.. 這不會(huì)被執(zhí)行
catch :lablename do
#.. 在遇到一個(gè) throw 后匹配將被執(zhí)行的 catch
end

實(shí)例

下面的實(shí)例中,如果用戶鍵入 '!' 回應(yīng)任何提示,使用一個(gè) 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:")

上面的程序需要人工交互,您可以在您的計(jì)算機(jī)上進(jìn)行嘗試。這將產(chǎn)生以下結(jié)果:

Name: Ruby on Rails
Age: 3
Sex: !
Name:Just Ruby

類 Exception

Ruby 的標(biāo)準(zhǔn)類和模塊拋出異常。所有的異常類組成一個(gè)層次,包括頂部的 Exception 類在內(nèi)。下一層是七種不同的類型:

  1.     Interrupt
  2.     NoMemoryError
  3.     SignalException
  4.     ScriptError
  5.     StandardError
  6.     SystemExit
  7.     Fatal 是該層中另一種異常,但是 Ruby 解釋器只在內(nèi)部使用它。

ScriptError 和 StandardError 都有一些子類,但是在這里我們不需要了解這些細(xì)節(jié)。最重要的事情是創(chuàng)建我們自己的異常類,它們必須是類 Exception 或其子代的子類。

讓我們看一個(gè)實(shí)例:

class FileSaveError  StandardError
  attr_reader :reason
  def initialize(reason)
   @reason = reason
  end
end

現(xiàn)在,看下面的實(shí)例,將用到上面的異常:

File.open(path, "w") do |file|
begin
  # 寫(xiě)出數(shù)據(jù) ...
rescue
  # 發(fā)生錯(cuò)誤
  raise FileSaveError.new($!)
end
end

在這里,最重要的一行是 raise FileSaveError.new($!)。我們調(diào)用 raise 來(lái)示意異常已經(jīng)發(fā)生,把它傳給 FileSaveError 的一個(gè)新的實(shí)例,由于特定的異常引起數(shù)據(jù)寫(xiě)入失敗。

您可能感興趣的文章:
  • ruby 異常處理:ensure
  • ruby 異常處理:rescue
  • Ruby中的異常處理代碼編寫(xiě)示例

標(biāo)簽:棗莊 甘孜 南昌 克拉瑪依 內(nèi)江 西雙版納 大慶 河池

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解Ruby中的異?!?,本文關(guān)鍵詞  詳解,Ruby,中的,異常,詳解,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《詳解Ruby中的異?!废嚓P(guān)的同類信息!
  • 本頁(yè)收集關(guān)于詳解Ruby中的異常的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章