2012-04-24 10 views
7

क्या class_eval & instance_evaldef को छोड़कर काम में कोई अंतर है? class_eval ब्लॉक def कक्षा के लिए विधि को परिभाषित करता है (यानी उदाहरण विधि) और instance_evaldef कक्षा (यानी क्लास विधि) के eigenclass को विधि परिभाषित करता है। AFAIK अन्य सभी सुविधाएं दोनों मामलों में समान रूप से काम करती हैं (उदा। define_method, attr_accessor, class << self; end, स्थिरांक को परिभाषित करना)। क्या यह सच है?class_eval बनाम example_eval

उत्तर है: def, undef और aliasclass_eval और instance_eval के लिए विभिन्न संदर्भों की है।

उत्तर

13

लंबी कहानी कम:

  • (object = Object.new).instance_eval &block सेट:
  • Object.class_eval &block सेट:
    • selfObject
    • "वर्तमान वर्ग"

"वर्तमान वर्ग" def, undef और alias, साथ ही निरंतर और वर्ग चर लुकअप के लिए प्रयोग किया जाता है करने के लिए करने के लिए Object


अब, कार्यान्वयन विवरण देखें।

यहाँ कैसे module_eval और instance_eval सी में लागू किया जाता है है:

VALUE rb_mod_module_eval(int argc, VALUE *argv, VALUE mod) { 
    return specific_eval(argc, argv, mod, mod); 
} 

VALUE rb_obj_instance_eval(int argc, VALUE *argv, VALUE self) { 
    VALUE klass; 
    if (SPECIAL_CONST_P(self)) { klass = Qnil; } 
    else { klass = rb_singleton_class(self); } 
    return specific_eval(argc, argv, klass, self); 
} 

दोनों कॉल specific_eval है, जो निम्नलिखित तर्क होते हैं: int argc, VALUE *argv, VALUE klass और VALUE self

ध्यान दें कि:

  • module_eval गुजरता दोनों klassऔरself
  • instance_eval रूप Module या Class उदाहरण klass

के रूप में वस्तु की सिंगलटन वर्ग पास रहता है तो एक ब्लॉक दिया , specific_evalyield_under पर कॉल करेगा, जो निम्नलिखित तर्क लेता है: VALUE under, VALUE self और VALUE values

  1. block.self = self;

    यह सेट रिसीवर के लिए ब्लॉक के self:

    if (rb_block_given_p()) { 
        rb_check_arity(argc, 0, 0); 
        return yield_under(klass, self, Qundef); 
    } 
    

    yield_under में दो महत्वपूर्ण लाइनों रहे हैं।

  2. cref = vm_cref_push(th, under, NOEX_PUBLIC, blockptr);

    cref एक लिंक्ड सूची जो "वर्तमान वर्ग" है, जो def, undef और alias के लिए प्रयोग किया जाता है, साथ ही के रूप में निरंतर और वर्ग चर लुकअप निर्दिष्ट करता है।

    वह पंक्ति मूल रूप से cref से under पर सेट करती है।

    अंत:

    • जब module_eval से कहा जाता है, underClass या Module उदाहरण होगा।

    • जब instance_eval से कहा जाता है, underसिंगलटन वर्ग self की हो जाएगा।

+1

वहाँ एक बात है: अंदर 'class_eval' स्थिरांक और वर्ग चर बताए/जिस तरह से यह वर्ग परिभाषा में काम करता है काम नहीं करता है फिर से खोलने: यह बाहरी दायरे का उपयोग करता है। – Alexey

+0

@Alexey, आप सही हैं। मुझे यकीन है कि इसमें उस 'NODE_FL_CREF_PUSHED_BY_EVAL' स्थिरांक के साथ कुछ करना है। कई तरीकों, जैसे ['मॉड्यूल :: नेस्टिंग '] (http://ruby-doc.org/core-1.9.3/Module.html#method-c-nesting) उदाहरण के लिए, एक' क्रेफ 'नोड को अनदेखा करना प्रतीत होता है अगर ध्वज सेट है। –

0

instance_eval आपको इंस्टेंस के इंस्टेंस वैरिएबल को सीधे एक्सेस करने देता है, और उदाहरण के संदर्भ के रूप में self का उपयोग करने देता है।

+1

'class_eval' और' instance_eval' कि संबंध में हूबहू काम – Alexey

संबंधित मुद्दे