如果我有一個StandardError實例,消息存儲在哪裏?Ruby異常實例在哪裏保存消息?
s = StandardError.new("hi")
s.message # => "hi"
s.instance_variables # => []
s.instance_variable_get(:@message) # => nil
s.inspect # => "#<StandardError: hi>"
如果我有一個StandardError實例,消息存儲在哪裏?Ruby異常實例在哪裏保存消息?
s = StandardError.new("hi")
s.message # => "hi"
s.instance_variables # => []
s.instance_variable_get(:@message) # => nil
s.inspect # => "#<StandardError: hi>"
在對Ruby和C進行了一些調查之後,我發現異常類設置了一個名稱爲mesg
的實例變量。這不能在標準的Ruby運行時中訪問,因爲它不是以@
開頭的。
可以添加一個Ruby擴展,它可以讓你獲取和設置不帶前綴@
的實例變量。我不知道這可能有多危險。
I2C模塊:
#include "ruby.h"
static VALUE rb_mIvar;
static VALUE rb_ivar_iv_get(VALUE self, VALUE key) {
return rb_ivar_get(self, rb_to_id(key));
}
static VALUE rb_ivar_iv_set(VALUE self, VALUE key, VALUE value) {
return rb_ivar_set(self, rb_to_id(key), value);
}
void Init_ivar() {
rb_mIvar = rb_define_module("Ivar");
rb_define_method(rb_mIvar, "ivar_get", rb_ivar_iv_get, 1);
rb_define_method(rb_mIvar, "ivar_set", rb_ivar_iv_set, 2);
}
紅寶石用法:
$:.unshift('.')
require 'ivar'
Object.send(:include, Ivar)
e = StandardError.new("foo")
puts "Error message is: #{e.message}" # => e.message is "foo"
e.ivar_set(:mesg, "bar")
puts "Error message is: #{e.message}" # => e.message is now "bar"
看到這個要點有完整的代碼我用來研究和實驗:https://gist.github.com/adamhunter/5041075
由s.message # => "hi"
呼叫繼而調用to_s
方法返回的消息。更多:Ruby Exception
另外,請注意並非Ruby的所有部分都是用Ruby編寫的,特別是對於像Exception或StandardError這樣的非常基本的類。
通過查看Exception類的消息方法的來源,您可以找到答案(點擊然後轉到消息方法並使用小型放大鏡顯示源代碼)。這段代碼是C,而不是Ruby。
感謝鏈接Exception類。我已經做了一些挖掘工作,以找出在C中處理這些細節的具體細節,並在此問題上發佈了我的結果。 – Adam 2013-02-26 19:06:53