iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 28
0
Software Development

Ruby 研究 30 天系列 第 28

Day 27 - 例外處理

  • 分享至 

  • xImage
  •  

例外處理是幾乎每種程式語言都具備的功能,這個功能讓軟體工程師可以在程式出現非預期狀況的時候,能夠及時處理例外,並且設計處理每種例外的不同解決方式。

Ruby 能以區隔的 (compartmentalized) 方式處理例外的程式碼區塊。標示有 begin 的程式碼區塊執行後若遇到例外,就將控制轉移至標示有 rescue 的錯誤處理程式碼區塊,若沒有出現例外,就不會使用 rescue 程式碼。

begin
  # 有可能發生例外的處理動作
rescue
  # 例外發生時的處理措施
ensure
  # 無論有沒有發生例外,這一段都一定會執行
end

而錯誤有百百種(如圖),其中最常見的 Syntax Error 以及 NoMethod Error

https://ithelp.ithome.com.tw/upload/images/20191122/20120823TKI9EICLlg.png

其實例外處理也是一種流程控制,像是 fo..inwhileif..else 一樣。

begin 
  # 可能出現例外的程式碼
rescue SyntaxError
  # 出現SyntaxError時執行此行程式碼
rescue NoMethod Error
  # 出現ArgumentError時執行此行程式碼
end

Raise

但工程師都是小心的生物,並不是每一次程式碼都會遇到錯誤,特別是在簡單的程式碼,所以首先我們要先介紹如何手動產生例外,也就是 raise 方法。

def exception_example
  puts "例外開始前"
  raise  StandardError, "例外發生"
  puts "例外發生後"
end

exception_example 
# 印出以下內容
# 例外開始前
# `exception_example': 例外發生 (StandardError)

raise 來產生例外,如果你指定的引數只有一個,且為字串,raise 會建立RuntimeError 並將字串當作錯誤訊息,簡單的說, raise 方法(例外名稱:預設值為 RuntimeError , 例外訊息)。

def exception_example
  puts "例外開始前"
  raise "例外發生"
  puts "例外發生後"
end

exception_example 
# 印出以下內容
# 例外開始前
# `exception_example': 例外發生 (RuntimeError)

自訂

如果需要的話我們可以自訂例外類別,這裡有兩個原則:

  1. 繼承一個標準例外的類別,通常是 StandardError 。
  2. 以 Error 為自訂類別名稱的字尾。

class CoffeeTooWeakError < StandardError; end

raise(CoffeeTooWeakError, "coffee to water ratio too low")

藉由自訂例外的類別以指定的方式來辨識錯誤訊息,也許其他人透過程式碼就能選擇該如何處理這些錯誤的類型。

Retry

而當我們希望 rescue 能夠持續處理錯誤直到錯誤排除時可以用 retry 方法。

def greater_than_three(num)
  begin
    puts num    
    raise if num <= 3    # 引發例外,進入 rescue
  rescue
    num += 1
    retry
  ensure
    puts "已調整為#{num}"
  end
end

greater_than_three(1)
# 印出以下內容
# 1
# 2
# 3
# 4
# 已調整為4

最後,Ruby style :當例外的 beginend 的範圍剛好就是整個方法的範圍,我們可以省略 beginend

def greater_than_three(num)
  puts num    
  raise if num <= 3     # 引發例外,進入 rescue
  rescue
    num += 1
    retry
  ensure
    puts "已調整為#{num}"
end

此文同步刊登於CJ-Han的網站


上一篇
Day 26 - == , === , eql? , equal?
下一篇
Day 28 - Gemfile
系列文
Ruby 研究 30 天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言