2012-01-23 14 views
5

मैं एक बाहरी फ़ाइल के भीतर बाहरी फ़ाइलें लोड हो रहा हैएक वर्ग/मॉड्यूल

class A 
    some_definitions 
end 

और मैं लोड करने के लिए कि मॉड्यूल B ताकि वर्ग A ऊपर परिभाषित करने के लिए भेजा जा सकता है के भीतर चाहते हैं B::A के रूप में। मैंने कोशिश की:

class B 
    load('path_to_external_file.rb') 
end 

लेकिन A, मुख्य वातावरण में परिभाषित किया गया है B में नहीं:

A #=> A 
B.constants # => [] 

कैसे मैं कुछ वर्ग/मॉड्यूल के भीतर बाहरी फ़ाइलें लोड कर सकते हैं?

संपादित मैं तार के रूप में बाहरी फ़ाइलों को पढ़ने चाहिए, और Class.new{...} के भीतर उन्हें मूल्यांकन, और includeB भीतर उस वर्ग?

+0

किस अंत तक? आप कक्षा ए का सीधे उपयोग क्यों नहीं कर सकते?क्या आपको इसे मॉड्यूलर करने से कुछ लाभ मिल रहा है? 'लोड' और' आवश्यकता 'वास्तव में किसी मॉड्यूल में कक्षा को लोड नहीं करेगा, वे केवल स्रोत कोड लोड करते हैं, इसलिए आपकी कक्षाएं ठीक उसी तरह परिभाषित होती हैं जैसे वे फ़ाइल में हैं। यकीन नहीं है कि आप ऐसा क्यों करना चाहते हैं? – brad

+1

@brad क्योंकि इन बाहरी फ़ाइलों को उपयोगकर्ताओं द्वारा लिखा जाना है, और मनमाने ढंग से नामित किया जा सकता है। यदि मैं उन वर्गों को मुख्य वातावरण में परिभाषित करता हूं, तो वे नामकरण स्थान को गड़बड़ कर देंगे। – sawa

+0

'ऑब्जेक्टस्पेस # प्रत्येक_बोजेक्ट' के माध्यम से अन्य नामस्थानों के साथ छेड़छाड़ से सावधान रहें। – Reactormonk

उत्तर

4

आप नहीं कर सकते। कम से कम load या require का उपयोग करके, रूबी फ़ाइलों का हमेशा शीर्ष संदर्भ में मूल्यांकन किया जाएगा।

आप दो तरह से है कि समस्या को हल करने कर सकते हैं:

  • सीधे परिभाषित class B::A (लेकिन आप शायद उस से बचने के लिए कोशिश कर रहे हैं)
  • उपयोग eval(File.read("path_to_external_file.rb")) अपने B वर्ग के भीतर

संपादित करें : शायद, यह पुस्तकालय आपके लिए दिलचस्प है: https://github.com/dreamcat4/script/blob/master/intro.txt

3

आम तौर पर, कक्षा को "कक्षा ए" के रूप में परिभाषित करना एक बुरा विचार है, लेकिन फिर "जादूगर" इसे मॉड्यूल बी द्वारा निहित करता है। यदि आप कक्षा ए को बी :: ए के रूप में संदर्भित करना चाहते हैं, तो आपको इसे या तो परिभाषित करना चाहिए:

module B 
    class A 
    # contents 
    end 
end 

या:

class B::A 
    # contents 
end 

अन्यथा जो कोई पढ़ता अपने कोड भ्रमित हो जाएगा। इस मामले में, आपको "चाल" का उपयोग करके स्पष्टता, संक्षिप्तता या सुविधा में कुछ भी हासिल नहीं होता है, इसलिए सरल कोड बेहतर होता है। यहां एक सबक है: रुबी की मेटाप्रोग्रामिंग विशेषताएं बहुत अच्छी हैं, लेकिन उन्हें मुफ्त में उपयोग करने की आवश्यकता नहीं है। केवल तब ही उनका उपयोग करें जब आप वास्तव में ऐसा करने से कुछ प्राप्त करते हैं। अन्यथा आप बस अपना कोड समझने के लिए कठिन बनाते हैं।

लेकिन, अपनी टिप्पणी पढ़ने के बाद, ऐसा लगता है कि आपके मामले में ऐसा कुछ करने का वास्तव में एक अच्छा कारण है। मेरा सुझाव है कि निम्नलिखित समाधान आपके द्वारा कल्पना की जा रही तुलना में भी बेहतर होगा:

m = Module.new 
m.module_eval("class C; end") 
m.constants 
=> [:C] 
m.const_get(:C) 
=> #<Module:0xfd0da0>::C 

आप देखते हैं? यदि आप "गारंटीकृत अद्वितीय" नामस्थान चाहते हैं, तो आप एक अज्ञात मॉड्यूल का उपयोग कर सकते हैं। आप इन मॉड्यूल को हैश या अन्य डेटा संरचना में स्टोर कर सकते हैं, और कक्षाओं को आवश्यकतानुसार उनमें से खींच सकते हैं। इससे आपके द्वारा उल्लिखित समस्या हल हो जाती है, कि आपके ऐप के उपयोगकर्ता अपनी कक्षाएं जोड़ रहे हैं, और आप नहीं चाहते कि नाम टकरा जाए।

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