2012-01-02 6 views
7

मैं हाल ही में कुछ रूबी मेटा प्रोग्रामिंग का अभ्यास कर रहा हूं, और assigning anonymous classes to constants के बारे में सोच रहा था।क्या कोई हुक है जब अज्ञात कक्षाएं निरंतर असाइन की जाती हैं?

anonymous_class = Class.new # => #<Class:0x007f9c5afb21d0> 

इस वर्ग की नई उदाहरणों बनाया जा सकता है:

an_instance = anonymous_class.new # => #<#<Class:0x007f9c5afb21d0>:0x007f9c5afb0330> 

अब, जब गुमनाम वर्ग के लिए आवंटित किया गया है

रूबी में, यह इस प्रकार एक अनाम वर्ग बनाने के लिए संभव है एक निरंतर, कक्षा में अब उचित नाम है:

Foo = anonymous_class # => Foo 

और पहले बनाए गए उदाहरण

an_instance # => #<Foo:0x007f9c5afb0330> 

मेरा प्रश्न: जब एक गुमनाम वर्ग एक निरंतर को सौंपा गया है पल के लिए एक हुक विधि वहाँ अब भी उस वर्ग का एक उदाहरण है?

रुबी में hooks methods हैं, लेकिन मुझे यह नहीं मिला।

+0

बहुत ही रोचक सवाल। –

+1

AFAIK अभी भी वैरिएबल असाइनमेंट के लिए कोई हुक नहीं है, निरंतर या अन्यथा ([बहुत समय पहले एक ही प्रश्न के लिए देखें] (http://www.ruby-forum.com/topic/65720))। ग्लोबल्स, हां। –

उत्तर

6

चलो देखते हैं कि निरंतर असाइनमेंट आंतरिक रूप से कैसे काम करता है। निम्नानुसार कोड रूबी-1.9.3-पी 0 के स्रोत टैरबॉल से निकाला जाता है। पहले हम वी एम अनुदेश setconstant (जो स्थिरांक आवंटित करने के लिए प्रयोग किया जाता है) की परिभाषा को देखो:

# /insns.def, line 239 
DEFINE_INSN 
setconstant 
(ID id) 
(VALUE val, VALUE cbase) 
() 
{ 
    vm_check_if_namespace(cbase); 
    rb_const_set(cbase, id, val); 
    INC_VM_STATE_VERSION(); 
} 

vm_check_if_namespace या INC_VM_STATE_VERSION यहाँ में एक हुक जगह कोई संभावना नहीं है। , समारोह है कि हर एक निरंतर असाइन किया गया है कहा जाता है: तो हम rb_const_set को देखो (1886variable.c):

# /variable.c, line 1886 
void 
rb_const_set(VALUE klass, ID id, VALUE val) 
{ 
    rb_const_entry_t *ce; 
    VALUE visibility = CONST_PUBLIC; 

    # ... 

    check_before_mod_set(klass, id, val, "constant"); 
    if (!RCLASS_CONST_TBL(klass)) { 
     RCLASS_CONST_TBL(klass) = st_init_numtable(); 
    } 
    else { 
     # [snip], won't be called on first assignment 
    } 

    rb_vm_change_state(); 

    ce = ALLOC(rb_const_entry_t); 
    ce->flag = (rb_const_flag_t)visibility; 
    ce->value = val; 

    st_insert(RCLASS_CONST_TBL(klass), (st_data_t)id, (st_data_t)ce); 
} 

मैं सभी कोड है कि पहली बार एक निरंतर सौंपा गया था आमंत्रित नहीं किया गया हटाया एक मॉड्यूल के अंदर। मैंने फिर इस द्वारा बुलाए गए सभी कार्यों में देखा और एक भी बिंदु नहीं मिला जहां हम रूबी कोड से एक हुक लगा सकते थे। इसका मतलब है कि सख्त सत्य तब तक है जब तक कि मुझे कुछ याद नहीं आया, कि कोई निरंतर असाइनमेंट (कम से कम एमआरआई में) को हुक करने के लिए है।

अद्यतन

स्पष्ट करने के लिए: गुमनाम वर्ग नहीं जादुई रूप में जल्द ही एक नया नाम मिल उसके असाइन (के रूप में एंड्रयू जवाब में सही ढंग से ध्यान दिया)। इसके बजाय, वर्ग की ऑब्जेक्ट आईडी के साथ निरंतर नाम रूबी की आंतरिक निरंतर लुकअप तालिका में संग्रहीत किया जाता है। यदि, उसके बाद, कक्षा का नाम अनुरोध किया जाता है, तो इसे अब उचित नाम (और केवल Class:0xXXXXXXXX...) के लिए हल किया जा सकता है।

तो इस असाइनमेंट पर प्रतिक्रिया करने के लिए आप सबसे अच्छा कर सकते हैं, पृष्ठभूमि कार्यकर्ता थ्रेड के लूप में कक्षा के name को जांचना है जब तक यह गैर-nil (जो संसाधनों का एक बड़ा अपशिष्ट है, आईएमएचओ) है।

+0

बहुत व्यापक उत्तर के लिए धन्यवाद। इसे पूरा करने के लिए, आपको 'setconstant'' के संदर्भ में यह संदर्भ कैसे मिला? स्रोत ('insns.def') में प्रलेखन मेरे लिए बहुत स्पष्ट नहीं है:" स्थिर चर आईडी सेट करें। अगर क्लास Qfalse है, तो निरंतर इस दायरे में पहुंचने में सक्षम है। अगर क्लास Qnil है, तो शीर्ष स्तर स्थिर सेट करें। अन्यथा, क्लास वर्ग या मॉड्यूल के तहत निरंतर सेट करें। " क्या यह कोड वास्तव में (अज्ञात) कक्षा के उदाहरणों को स्थिरांक असाइन करने के लिए उपयोग किया जाता है? – rdvdijk

+0

@rdvdijk: मैंने अनुमान लगाया और इसे 'printf' के साथ सत्यापित किया। –

+0

मैंने आपके द्वारा संदर्भित स्रोत कोड में देखा है, और आपके द्वारा चिपकाए गए कोड के अर्थ को समझ लिया है। हालांकि, यह मेरे प्रश्न का पूरी तरह उत्तर नहीं देता है। यह कोड स्थिरांक के असाइनमेंट को संभालने से पता चलता है, और इस कोड में कोई हुक उपलब्ध नहीं है। हालांकि, यह समझा नहीं जाता है कि अनाम वर्ग कब और कहां अपने नए नाम के बारे में पता लगाता है। एंड्रयू ग्रिम के जवाब के बाद, ऐसा लगता है कि विधि 'वर्गनाम' और संबंधित कोड 'RCLASS_CONST_TBL' या 'rb_class_tbl' में निरंतर दिखता है, है ना? – rdvdijk

0

बेनामी कक्षाएं वास्तव में अपना नाम प्राप्त नहीं करती हैं जब उन्हें निरंतर असाइन किया जाता है। वे वास्तव में इसे प्राप्त करते हैं जब उन्हें अगली बार पूछा जाता है कि उनका नाम क्या है।

मैं इसके लिए एक संदर्भ खोजने की कोशिश करूंगा। संपादित करें: कोई नहीं ढूंढ सकता, क्षमा करें।

+0

कुंजी 'variable.c: 305' (ruby-1.9.3-p0) में परिभाषित फ़ंक्शन' rb_class_name' है और इसके द्वारा बुलाए गए फ़ंक्शंस (विशेष रूप से 'find_class_path', जो 'RCLASS_CONST_TBL' मानचित्र का उपयोग करता है यह जांचने के लिए कि क्या है कक्षा एक नाम से बंधी है, कम से कम अगर मेरी व्याख्या सही है)। –

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