2010-06-10 8 views
5

निम्नलिखित एक्सटेंशन पर विचार करें (वर्षों में कई रेल प्लगइन्स द्वारा लोकप्रिय पैटर्न):मैक्रो-जैसी मेटाप्रोग्रामिंग विधियों के साथ आप रूबी मॉड्यूल का विस्तार कैसे करते हैं?

module Extension 
    def self.included(recipient) 
    recipient.extend ClassMethods 
    recipient.send :include, InstanceMethods 
    end 

    module ClassMethods 
    def macro_method 
     puts "Called macro_method within #{self.name}" 
    end 
    end 

    module InstanceMethods 
    def instance_method 
     puts "Called instance_method within #{self.object_id}" 
    end 
    end 
end 

यदि आप इसे प्रत्येक वर्ग में बेनकाब करना चाहते हैं, तो आप निम्न कार्य कर सकते हैं:

Object.send :include, Extension 

अब आप किसी भी वर्ग को परिभाषित कर सकते हैं और मैक्रो विधि का उपयोग कर सकते हैं:

class FooClass 
    macro_method 
end 
#=> Called macro_method within FooClass 

और उदाहरण उदाहरण विधियों का उपयोग कर सकते हैं:

FooClass.new.instance_method 
#=> Called instance_method within 2148182320 

लेकिन Module.is_a?(Object) के बावजूद, आप मॉड्यूल में मैक्रो विधि का उपयोग नहीं कर सकते हैं।

module FooModule 
    macro_method 
end 
#=> undefined local variable or method `macro_method' for FooModule:Module (NameError) 

यह सच है भले ही आप Module.send(:include, Extension) के साथ Module में मूल Extension स्पष्ट रूप से शामिल करें।

व्यक्तिगत मॉड्यूल के लिए आप हाथ से एक्सटेंशन शामिल कर सकते हैं और एक ही प्रभाव प्राप्त कर सकते हैं:

module FooModule 
    include Extension 
    macro_method 
end 
#=> Called macro_method within FooModule 

लेकिन आप सभी रूबी मॉड्यूल में मैक्रो-जैसी विधियों को कैसे जोड़ते हैं?

उत्तर

22

पर विचार करें निम्नलिखित एक्सटेंशन (पैटर्न वर्षों में कई रेल प्लगइन्स द्वारा लोकप्रिय बनाया)

यह नहीं एक पैटर्न है, और यह "को लोकप्रिय बनाया" नहीं किया गया। यह एंटी-पैटर्न है जो कार्गो-पंथ 1337 PHP h4X0rZ द्वारा रूबी को नहीं जानता है। शुक्र है, इस विरोधी पैटर्न के कई (सभी?) उदाहरण रेल 3 से समाप्त हो गए हैं, येहुदा काट्ज़, कार्ल लेर्चे और अन्य लोगों के कड़ी मेहनत के कारण धन्यवाद। येहुदा रेल कोड कोडबेस को साफ करने के बारे में हालिया वार्ता में एक एंटी-उदाहरण के रूप में पोस्ट किए गए सटीक उसी कोड का भी उपयोग करता है, और उसने इस एक विरोधी पैटर्न के बारे में an entire blog post लिखा था। आप Objectवैसे भी में जोड़ने के लिए है, तो क्यों सिर्फ इतना है कि नहीं करना चाहते हैं

Object.send :include, Extension 

:

आप हर वर्ग को यह बेनकाब करने के लिए कामना की, तो आप निम्न कर सकते हैं:

class Object 
    def instance_method 
    puts "Called instance_method within #{inspect}" 
    end 
end 

लेकिन आप सभी रूबी मॉड्यूल करने के लिए मैक्रो की तरह तरीकों जोड़ सकता हूँ?

सरल: उन्हें Module को जोड़कर:

class Module 
    def macro_method 
    puts "Called macro_method within #{inspect}" 
    end 
end 

यह सब सिर्फ काम करता है:

class FooClass 
    macro_method 
end 
#=> Called macro_method within FooClass 

FooClass.new.instance_method 
#=> Called instance_method within #<FooClass:0x192abe0> 

module FooModule 
    macro_method 
end 
#=> Called macro_method within FooModule 

यह बनाम अपने 16 कोड का सिर्फ 10 लाइनों है, और निश्चित रूप से 0 लोगों के बीच 10 रेखाएं मेटाप्रोग्रामिंग या हुक या कुछ भी दूरस्थ रूप से जटिल हैं।

अपने कोड और मेरा के बीच फर्क सिर्फ इतना है कि अपने कोड में, mixins अप वंशानुगत पदानुक्रम में, दिखाने तो यह एक बालक डिबग करने के लिए आसान है, क्योंकि आप वास्तव में कि कुछ Object को जोड़ा गया है देखते हैं। और

module ObjectExtensions 
    def instance_method 
    puts "Called instance_method within #{inspect}" 
    end 
end 

class Object 
    include ObjectExtensions 
end 

module ModuleExtensions 
    def macro_method 
    puts "Called macro_method within #{inspect}" 
    end 
end 

class Module 
    include ModuleExtensions 
end 

अब मैं 16 लाइनों पर अपने कोड के साथ करार कर रहा हूँ, लेकिन मैं तर्क था कि मेरा तुम्हारा से अधिक आसान है, खासकर यह देखते हुए कि तुम्हारा काम नहीं करता है न तो आप और न ही मैं और न ही लगभग: लेकिन है कि आसानी से तय हो गई है 1 9 0000 स्टैक ओवरव्लो उपयोगकर्ता क्यों पता लगा सकते हैं।

+1

* * वह ब्लॉग पोस्ट है। मुझे पता था कि मैंने इसे हाल ही में देखा होगा। अभी भी उत्सुक है कि दूसरी रणनीति क्यों काम नहीं करती है, और मुझे विश्वास नहीं है कि यह एक मामूली दोष के रूप में एक गंभीर विरोधी पैटर्न है, लेकिन मैं सहमत हूं कि मूल रूप से "ओवरराइडिंग में कोई बात नहीं है, जब विस्तार की तरह व्यवहार करना शामिल है रूबी दोनों प्रदान करता है। " "कार्गो-पंथ" के लिए –

+3

+1। –

+0

क्या आपने "macro_method" को परिभाषित करने का कोई तरीका है, लेकिन यह चुनने में सक्षम है कि किन वर्गों तक इसका उपयोग है? –

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