असल में, कक्षा में नए तरीकों को जोड़ने के कुछ अन्य तरीके हैं। उदाहरण के लिए, आप मॉड्यूल में विधियों को भी परिभाषित कर सकते हैं, और मॉड्यूल को मूल वर्ग में मिला सकते हैं।
module ExtraMethods
def bar
end
end
Foo.class_eval { include ExtraMethods }
class Foo
include ExtraMethods
end
कोई वास्तविक या बुरा नहीं है। आपके द्वारा वर्णित दो (या तीन) तरीकों में अलग-अलग व्यवहार हैं और आप अपनी आवश्यकता (या वरीयता) के आधार पर एक या दूसरे का उपयोग करना चाह सकते हैं। ज्यादातर मामलों में, यह व्यक्तिपरक है। अन्य मामलों में, यह वास्तव में इस पर निर्भर करता है कि आपका कोड कैसे संरचित किया गया है।
class_eval
का उपयोग कर वर्ग बनाम फिर से खोलने के बीच मुख्य उद्देश्य अंतर यह है कि पहला व्यक्ति वर्ग परिभाषा भी है, जबकि दूसरे को मूल वर्ग को पहले ही परिभाषित करने की आवश्यकता है।
अभ्यास में, कुछ मामलों में कक्षा को फिर से खोलने से कुछ अप्रत्याशित दुष्प्रभाव हो सकते हैं। मान लीजिए कि आपने Foo
को lib/foo.rb
फ़ाइल में विधियों के समूह के साथ परिभाषित किया है। फिर आप को config/initializers/extra.rb
में फिर से खोलें और आप bar
विधि जोड़ें।
myclass.rb
में आप Foo
का उपयोग करते हैं, लेकिन lib/foo.rb
मैन्युअल रूप से आवश्यक होने की बजाय, आप एक ऑटोलोड लोड पर भरोसा करते हैं।
extra.rb
lib/foo.rb
से पहले भरी हुई है, तो क्या हो सकता है कि Foo
वर्ग पहले से ही अपने वातावरण में परिभाषित किया गया है, और अपने कोड lib/foo.rb
लोड नहीं होगा है। आपके पास Foo
क्लास होगा जो आपके द्वारा परिभाषित bar
एक्सटेंशन है, और मूल Foo
एक नहीं है।
दूसरे शब्दों में, यदि किसी भी कारण से आप क्लास को फिर से खोलने के लिए कुछ तरीकों को जोड़ने के लिए पूर्ण उत्पत्ति वर्ग परिभाषा को पहले लोड किया गया है (या उसके बाद), तो यह कोड टूट सकता है अगर यह ऑटोलोड पर निर्भर करता है।
इसके विपरीत, Foo.class_eval
Foo
पर एक विधि कॉल करता है, इसलिए यह नई विधियों को जोड़ने का प्रयास करते समय मूल Foo
परिभाषा पहले से मौजूद होने की अपेक्षा करता है। यह सुनिश्चित करता है कि, जब आप नई विधियां जोड़ते हैं, तो Foo
कक्षा पहले ही परिभाषित की जाएगी।
निष्कर्ष में, मुख्य अंतर यह है कि कक्षा को दोबारा खोलने से आपको कक्षा में विधियों को जोड़ने की अनुमति मिलती है जो अभी तक लोड नहीं हो सकते हैं, जबकि class_eval
कक्षा को पहले ही परिभाषित करने की आवश्यकता है।
सामान्य रूप से, जब तक कि मैं नामित उप-वर्गों को परिभाषित नहीं कर रहा हूं या कक्षाओं को दोबारा खोल रहा हूं, मेरा पूरा नियंत्रण है, मैं दूसरे कोड को पसंद करता हूं क्योंकि बड़े कोडबेस में यह कोड को और अधिक रखरखाव करता है। असल में, मैं आमतौर पर मिश्रित का उपयोग करता हूं यदि मैं तीसरे पक्ष के वर्गों का विस्तार करता हूं ताकि अगर मैं मौजूदा तरीकों को ओवरराइड करने की आवश्यकता हो तो मैं पूर्ण विधि पूर्वजों श्रृंखला को बनाए रख सकता हूं।
[ 'फू # define_method'] (http://ruby-doc.org/core-2.2.0/Module.html#method-i-define_method) भी। – mudasobwa