如果跟蹤通過1.9.3源代碼,你會發現defined?
在insns.def
實現:
DEFINE_INSN
defined
(rb_num_t op_type, VALUE obj, VALUE needstr)
/* ... */
switch (type) {
/* ... */
case DEFINED_CONST:
klass = v;
if (vm_get_ev_const(th, GET_ISEQ(), klass, SYM2ID(obj), 1)) {
expr_type = "constant";
}
break;
所以,當你defined? SomeConstant
,您通過大switch
涓流,並最終調用vm_get_ev_const
。該功能在vm_insnhelper.c
定義:
static inline VALUE
vm_get_ev_const(rb_thread_t *th, const rb_iseq_t *iseq,
VALUE orig_klass, ID id, int is_defined)
這個功能恰好是靜態的,所以你不能得到它。看起來像vm_get_ev_const
是根據rb_const_defined
和rb_const_defined_from
定義的,並且這兩個都應該在C中可用,因此您可以嘗試這些;但是您必須爲這些人找到正確的klass
。
或者你可以去你的主意,只是使用Object.const_defined?
。其中一個問題是,它不會像A::B
這樣的事情做正確的事情,你必須說Object.const_defined? :A && A.const_defined? :B
因爲Object.const_defined? :'A::B'
只會拋出一個異常在你的臉上。這裏的一般解決方案需要迭代和類查找。但是,如果您正在查看的類都在頂級命名空間中,那麼一個簡單的Object.const_defined?
應該可以做到。
'Object.const_defined?'可能會像你想要的那樣好。實際的'defined?'關鍵字在'insns.def'中執行(查找'DEFINE_INSN'),並調用'vm_get_ev_const',它在'vm_insnhelper.c'中是靜態的,因此不可訪問。 –
我認爲你是對的,謝謝!你想做出答案嗎? :) – d11wtq
我放下了一些筆記,但它不是(當然)總是像Object.const_defined?一樣簡單。當然。 –