類別 Exception
類別 Exception
及其子類別用於在 Kernel#raise
和 begin ... end
區塊中的 rescue
陳述式之間進行溝通。
一個 Exception
物件會傳遞有關例外狀況的資訊
-
其類型(例外的類別)。
-
一個選用的描述性訊息。
-
選用的追蹤資訊。
某些 Exception
的內建子類別有其他方法:例如 NameError#name
。
預設值¶ ↑
兩個 Ruby 陳述式有預設的例外類別
-
raise
:預設為RuntimeError
。 -
rescue
:預設為StandardError
。
全域變數¶ ↑
當一個例外狀況已經被引發但尚未被處理(在 rescue
、ensure
、at_exit
和 END
區塊中),會設定兩個全域變數
-
$!
包含目前的例外狀況。 -
$@
包含其追蹤資訊。
自訂例外¶ ↑
為了提供其他或替代資訊,一個程式可以建立自訂的例外類別,這些類別衍生自內建的例外類別。
一個良好的做法是,讓程式庫建立一個單一的「一般」例外類別(通常是 StandardError
或 RuntimeError
的子類別),並讓其他例外類別繼承這個類別。這允許使用者救援一般例外,從而捕捉程式庫可能引發的所有例外,即使程式庫的未來版本新增了新的例外子類別。
例如
class MyLibrary class Error < ::StandardError end class WidgetError < Error end class FrobError < Error end end
為了處理 MyLibrary::WidgetError 和 MyLibrary::FrobError,程式庫使用者可以救援 MyLibrary::Error。
內建 Exception
類別¶ ↑
Exception
的內建子類別為
-
fatal
公開類別方法
如果沒有參數,或參數與接收者相同,則傳回接收者。否則,建立一個與接收者同類別的新例外物件,但訊息等於 字串.to_str
。
建構一個新的 Exception
物件,並可選擇傳入訊息。
static VALUE exc_initialize(int argc, VALUE *argv, VALUE exc) { VALUE arg; arg = (!rb_check_arity(argc, 0, 1) ? Qnil : argv[0]); return exc_init(exc, arg); }
如果例外訊息將傳送到 tty,則傳回 true
。
static VALUE exc_s_to_tty_p(VALUE self) { return RBOOL(rb_stderr_tty_p()); }
公開實例方法
相等性—如果 obj 不是 Exception
,則傳回 false
。否則,如果 exc 和 obj 共享相同的類別、訊息和追蹤,則傳回 true
。
static VALUE exc_equal(VALUE exc, VALUE obj) { VALUE mesg, backtrace; if (exc == obj) return Qtrue; if (rb_obj_class(exc) != rb_obj_class(obj)) { int state; obj = rb_protect(try_convert_to_exception, obj, &state); if (state || UNDEF_P(obj)) { rb_set_errinfo(Qnil); return Qfalse; } if (rb_obj_class(exc) != rb_obj_class(obj)) return Qfalse; mesg = rb_check_funcall(obj, id_message, 0, 0); if (UNDEF_P(mesg)) return Qfalse; backtrace = rb_check_funcall(obj, id_backtrace, 0, 0); if (UNDEF_P(backtrace)) return Qfalse; } else { mesg = rb_attr_get(obj, id_mesg); backtrace = exc_backtrace(obj); } if (!rb_equal(rb_attr_get(exc, id_mesg), mesg)) return Qfalse; return rb_equal(exc_backtrace(exc), backtrace); }
傳回與例外狀況關聯的任何追蹤記錄。追蹤記錄是一個字串陣列,每個字串都包含「filename:lineNo: in ‘method」' 或「filename:lineNo」。
def a raise "boom" end def b a() end begin b() rescue => detail print detail.backtrace.join("\n") end
產生
prog.rb:2:in `a' prog.rb:6:in `b' prog.rb:10
如果未設定追蹤記錄,則傳回 nil
ex = StandardError.new ex.backtrace #=> nil
static VALUE exc_backtrace(VALUE exc) { VALUE obj; obj = rb_attr_get(exc, id_bt); if (rb_backtrace_p(obj)) { obj = rb_backtrace_to_str_ary(obj); /* rb_ivar_set(exc, id_bt, obj); */ } return obj; }
傳回與例外狀況關聯的任何追蹤記錄。此方法類似於 Exception#backtrace
,但追蹤記錄是 Thread::Backtrace::Location
的陣列。
此方法不受 Exception#set_backtrace()
影響。
static VALUE exc_backtrace_locations(VALUE exc) { VALUE obj; obj = rb_attr_get(exc, id_bt_locations); if (!NIL_P(obj)) { obj = rb_backtrace_to_location_ary(obj); } return obj; }
傳回此例外狀況引發時先前的例外狀況 ($!)。這對於包裝例外狀況和保留原始例外狀況資訊很有用。
static VALUE exc_cause(VALUE exc) { return rb_attr_get(exc, id_cause); }
處理 message
傳回的字串。
它可能會將例外狀況的類別名稱新增到第一行的結尾。此外,當 highlight
關鍵字為 true 時,它會新增 ANSI 逸出序列以將訊息設為粗體。
如果您覆寫此方法,則它必須容忍未知的關鍵字引數。傳遞給 full_message
的所有關鍵字引數都會委派給此方法。
此方法會被 did_you_mean 和 error_highlight 覆寫以新增其資訊。
使用者定義的例外狀況類別也可以定義自己的 detailed_message
方法以新增補充資訊。當 highlight
為 true 時,它可以傳回包含逸出序列的字串,但請使用廣泛支援的逸出序列。建議限制下列程式碼
-
重設 (
\e[0m
) -
粗體 (
\e[1m
) -
底線 (
\e[4m
) -
白色和黑色以外的前景顏色
-
紅色 (
\e[31m
) -
綠色 (
\e[32m
) -
黃色 (
\e[33m
) -
藍色 (
\e[34m
) -
洋紅色 (
\e[35m
) -
青色 (
\e[36m
)
-
即使 highlight
為 true,也要小心使用逸出序列。不要使用逸出序列來表達必要資訊;即使忽略所有逸出序列,訊息也應該可讀。
static VALUE exc_detailed_message(int argc, VALUE *argv, VALUE exc) { VALUE opt; rb_scan_args(argc, argv, "0:", &opt); VALUE highlight = check_highlight_keyword(opt, 0); extern VALUE rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight); return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight)); }
如果沒有參數,或參數與接收者相同,則傳回接收者。否則,建立一個與接收者同類別的新例外物件,但訊息等於 字串.to_str
。
static VALUE exc_exception(int argc, VALUE *argv, VALUE self) { VALUE exc; argc = rb_check_arity(argc, 0, 1); if (argc == 0) return self; if (argc == 1 && self == argv[0]) return self; exc = rb_obj_clone(self); rb_ivar_set(exc, id_mesg, argv[0]); return exc; }
傳回格式化的 exception 字串。傳回的字串會使用 Ruby 在將未捕捉的例外狀況列印到 stderr 時使用的相同格式進行格式化。
如果 highlight 為 true
,預設錯誤處理常式會將訊息傳送至 tty。
order 必須為 :top
或 :bottom
之一,並將錯誤訊息和最內層的 backtrace 放在頂端或底部。
這些選項的預設值取決於 $stderr
及其在呼叫時間的 tty?
。
static VALUE exc_full_message(int argc, VALUE *argv, VALUE exc) { VALUE opt, str, emesg, errat; VALUE highlight, order; rb_scan_args(argc, argv, "0:", &opt); highlight = check_highlight_keyword(opt, 1); order = check_order_keyword(opt); { if (NIL_P(opt)) opt = rb_hash_new(); rb_hash_aset(opt, sym_highlight, highlight); } str = rb_str_new2(""); errat = rb_get_backtrace(exc); emesg = rb_get_detailed_message(exc, opt); rb_error_write(exc, emesg, errat, str, opt, highlight, order); return str; }
傳回此例外狀況的類別名稱和訊息。
static VALUE exc_inspect(VALUE exc) { VALUE str, klass; klass = CLASS_OF(exc); exc = rb_obj_as_string(exc); if (RSTRING_LEN(exc) == 0) { return rb_class_name(klass); } str = rb_str_buf_new2("#<"); klass = rb_class_name(klass); rb_str_buf_append(str, klass); if (RTEST(rb_str_include(exc, rb_str_new2("\n")))) { rb_str_catf(str, ":%+"PRIsVALUE, exc); } else { rb_str_buf_cat(str, ": ", 2); rb_str_buf_append(str, exc); } rb_str_buf_cat(str, ">", 1); return str; }
傳回呼叫 exception.to_s
的結果。這通常會傳回例外狀況的訊息或名稱。
static VALUE exc_message(VALUE exc) { return rb_funcallv(exc, idTo_s, 0, 0); }
設定與 exc
關聯的 backtrace 資訊。backtrace
必須是 String
物件的陣列,或 String
,其格式如 Exception#backtrace
中所述。
static VALUE exc_set_backtrace(VALUE exc, VALUE bt) { return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt)); }
傳回例外狀況的訊息(如果未設定訊息,則傳回例外狀況的名稱)。
static VALUE exc_to_s(VALUE exc) { VALUE mesg = rb_attr_get(exc, idMesg); if (NIL_P(mesg)) return rb_class_name(CLASS_OF(exc)); return rb_String(mesg); }