2012-09-25 16 views
9

में आवृत्ति चर प्रारंभ करना क्या मिक्स्डिन के रूप में उपयोग किए जाने वाले मॉड्यूल में इंस्टेंस चर को प्रारंभ करने का कोई साफ तरीका है? - इस हल्का परेशान हैमिक्सिन

module Example 

    def on(...) 
    @handlers ||= {} 
    # do something with @handlers 
    end 

    def all(...) 
    @all_handlers ||= [] 
    # do something with @all_handlers 
    end 

    def unhandled(...) 
    @unhandled ||= [] 
    # do something with unhandled 
    end 

    def do_something(..) 
    @handlers  ||= {} 
    @unhandled ||= [] 
    @all_handlers ||= [] 

    # potentially do something with any of the 3 above 
    end 

end 

सूचना मैं बार-बार जांच करने के लिए करता है, तो प्रत्येक @member ठीक से प्रत्येक कार्य में शुरू कर दिया गया है: उदाहरण के लिए, मैं निम्नलिखित है। मैं बहुत अधिक लिखूंगा:

module Example 

    def initialize 
    @handlers  = {} 
    @unhandled = [] 
    @all_handlers = [] 
    end 

    # or 
    @handlers = {} 
    @unhandled = [] 
    # ... 
end 

और बार-बार यह सुनिश्चित करना नहीं है कि चीजें सही ढंग से शुरू हो जाएं। हालांकि, मैं यह कह सकता हूं कि यह संभव नहीं है। विधि Example पर जोड़ने और विस्तारित कक्षा से initialize_me पर कॉल करने के अलावा, इसके आसपास कोई रास्ता है? मैंने this example देखा, लेकिन ऐसा करने के लिए मैं बंदर-पैचिंग चीजें Class में नहीं हूं।

उत्तर

12
module Example 
    def self.included(base) 
    base.instance_variable_set :@example_ivar, :foo 
    end 
end 

संपादित: ध्यान दें कि यह एक वर्ग उदाहरण चर स्थापित कर रही है। उदाहरण पर इंस्टेंस वेरिएबल्स क्लास में मिश्रित होने पर नहीं बनाया जा सकता है, क्योंकि उन उदाहरणों को अभी तक नहीं बनाया गया है। आप, हालांकि, एक इनिशियलाइज़ विधि mixin में, उदा बना सकते हैं .:

module Example 
    def self.included(base) 
    base.class_exec do 
     def initialize 
     @example_ivar = :foo 
     end 
    end 
    end 
end 

सहित वर्ग के इनिशियलाइज़ विधि बुला जबकि ऐसा करने के लिए एक रास्ता हो सकता है (किसी को?)। निश्चित नहीं।

class Foo 
    include Example 

    def initialize 
    @foo = :bar 
    after_initialize 
    end 
end 

module Example 
    def after_initialize 
    @example_ivar = :foo 
    end 
end 
+0

उत्कृष्ट, धन्यवाद - मुझे आश्चर्य है कि मुझे इस दृष्टिकोण को कहीं भी क्यों नहीं देखा गया है, भले ही इसके बारे में लाखों लेख हैं। –

+0

दुर्भाग्यवश यह काम नहीं प्रतीत होता है - 'example_ivar' का संदर्भ देने के बाद' nil' के रूप में वापस आता है। –

+0

आह, मैं देखता हूं, धन्यवाद - लेकिन यदि कक्षा पहले से ही 'प्रारंभिक' विधि निर्दिष्ट करती है, तो इससे समस्याएं उत्पन्न हो जाएंगी, है ना? –

2

modules, हुक प्रदान करता है Module#included के रूप में: लेकिन यहाँ एक विकल्प है। मेरा सुझाव है कि आप विषय पर रूबी डॉक्टर देखें, या ActiveSupport::Concern का उपयोग करें, जो मॉड्यूल पर कुछ सहायक प्रदान करता है।

+0

मैं 'ActiveSupport' का उपयोग नहीं कर रहा हूं, लेकिन मुझे सही दिशा में इंगित करने के लिए धन्यवाद। –

+0

आपका स्वागत है। – ksol

1

शायद यह एक छोटे से hacky है, लेकिन आप prepend का उपयोग वांछित व्यवहार प्राप्त करने के लिए कर सकते हैं:

2.1.1 :011 > A.new 
=> #<A:0x00000101131788 @instance_var=[]> 
+0

क्या इसमें शामिल होने के बजाय प्रीपेड का उपयोग करने के लिए कोई डाउनसाइड्स हैं? –

+0

एक नकारात्मक पक्ष मैं सोच सकता हूं कि मॉड्यूल पदानुक्रम में कक्षा के नीचे डाला जाता है। आम तौर पर, हमारे प्रकार पदानुक्रम 'ए <फू <ऑब्जेक्ट' जैसा दिखता है, लेकिन अब हमारे पास 'Foo Max

+0

ठीक है :) अच्छी तरह से "प्रीपेन्ड" मुझे लगता है कि इसके बारे में काफी आत्म-स्पष्टीकरण है, इसलिए मुझे आपका समाधान पसंद है (धन्यवाद)! (+1 किए गए) –

0

मैं वहाँ एक हो सकता है लगता है:

module Foo 
    def initialize(*args) 
    @instance_var = [] 
    super 
    end 
end 

class A 
    prepend Foo 
end 

यहाँ कंसोल से उत्पादन होता है इसका आसान जवाब। मॉड्यूल में एक प्रारंभकर्ता होना चाहिए जो वैरिएबल को प्रारंभ करता है जैसा कि आप सामान्य रूप से करेंगे। कक्षा के प्रारंभकर्ता में जिसमें मॉड्यूल शामिल है, शामिल मॉड्यूल में प्रारंभकर्ता को आह्वान करने के लिए सुपर() को आमंत्रित करें। यह बस रूबी में विधि प्रेषण नियमों का पालन कर रहा है।

प्रतिबिंब पर, यह मॉड्यूल समेत कक्षा में भी एक सुपरक्लास है जिसे प्रारंभ करने की आवश्यकता है, तो यह बहुत अच्छा काम नहीं करेगा। मॉड्यूल में प्रारंभकर्ता को एक वैरिएबल पैरामीटर सूची स्वीकार करने और सुपरक्लास तक इसे पास करने की आवश्यकता होगी। हालांकि यह अन्वेषण करने के लिए एक अच्छा एवेन्यू जैसा दिखता है।

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