例外處理是幾乎每種程式語言都具備的功能,這個功能讓軟體工程師可以在程式出現非預期狀況的時候,能夠及時處理例外,並且設計處理每種例外的不同解決方式。
Ruby 能以區隔的 (compartmentalized) 方式處理例外的程式碼區塊。標示有
begin
的程式碼區塊執行後若遇到例外,就將控制轉移至標示有rescue
的錯誤處理程式碼區塊,若沒有出現例外,就不會使用rescue
程式碼。
begin
# 有可能發生例外的處理動作
rescue
# 例外發生時的處理措施
ensure
# 無論有沒有發生例外,這一段都一定會執行
end
而錯誤有百百種(如圖),其中最常見的 Syntax Error
以及 NoMethod Error
。
其實例外處理也是一種流程控制,像是 fo..in
、 while
、 if..else
一樣。
begin
# 可能出現例外的程式碼
rescue SyntaxError
# 出現SyntaxError時執行此行程式碼
rescue NoMethod Error
# 出現ArgumentError時執行此行程式碼
end
但工程師都是小心的生物,並不是每一次程式碼都會遇到錯誤,特別是在簡單的程式碼,所以首先我們要先介紹如何手動產生例外,也就是 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)
如果需要的話我們可以自訂例外類別,這裡有兩個原則:
class CoffeeTooWeakError < StandardError; end
raise(CoffeeTooWeakError, "coffee to water ratio too low")
藉由自訂例外的類別以指定的方式來辨識錯誤訊息,也許其他人透過程式碼就能選擇該如何處理這些錯誤的類型。
而當我們希望 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 :當例外的 begin
到 end
的範圍剛好就是整個方法的範圍,我們可以省略 begin
跟 end
。
def greater_than_three(num)
puts num
raise if num <= 3 # 引發例外,進入 rescue
rescue
num += 1
retry
ensure
puts "已調整為#{num}"
end
此文同步刊登於CJ-Han的網站