रूबी को महान बनाने वाली चीजों में से एक यह है कि हम अपनी जरूरतों के अनुसार लगभग कुछ भी कस्टमाइज़ कर सकते हैं। यह दोनों उपयोगी और खतरनाक है। अपने पैर पर कुल्हाड़ी मारना आसान है, लेकिन जब सावधानी से उपयोग किया जाता है, तो यह काफी शक्तिशाली समाधानों में परिणाम दे सकता है।
रूबी मैजिक में, हम सोचते हैं कि उपयोगी और खतरनाक एक उत्कृष्ट संयोजन है। आइए देखें कि रूबी ऑब्जेक्ट्स को कैसे बनाती और इनिशियलाइज़ करती है और हम डिफ़ॉल्ट व्यवहार को कैसे संशोधित कर सकते हैं।
क्लासेस से नए ऑब्जेक्ट्स बनाने की मूल बातें
शुरू करने के लिए, आइए देखें कि रूबी में ऑब्जेक्ट्स कैसे बनाएं। एक नया ऑब्जेक्ट (या इंस्टेंस) बनाने के लिए, हम क्लास पर new कॉल करते हैं। अन्य भाषाओं के विपरीत, new भाषा का कीवर्ड नहीं है, बल्कि एक मेथड है जिसे किसी अन्य की तरह ही कहा जाता है।
class Dog
end
object = Dog.new
नव निर्मित ऑब्जेक्ट को कस्टमाइज़ करने के लिए, new मेथड को आर्ग्युमेंट्स पास करना संभव है। जो कुछ भी आर्ग्युमेंट्स के रूप में पास किया जाता है, वह इनिशियलाइज़र को पास हो जाएगा।
class Dog
def initialize(name)
@name = name
end
end
object = Dog.new('Good boy')
फिर से, अन्य भाषाओं के विपरीत, रूबी में इनिशियलाइज़र भी कुछ विशेष सिंटैक्स या कीवर्ड के बजाय सिर्फ एक मेथड है।
इस बात को ध्यान में रखते हुए, क्या उन मेथड्स के साथ खिलवाड़ करना संभव नहीं होना चाहिए, ठीक वैसे ही जैसे किसी अन्य रूबी मेथड के साथ संभव है? बिल्कुल है!
एक सिंगल ऑब्जेक्ट के व्यवहार को संशोधित करना
मान लीजिए हम यह सुनिश्चित करना चाहते हैं कि किसी विशेष क्लास के सभी ऑब्जेक्ट्स हमेशा लॉग स्टेटमेंट्स प्रिंट करेंगे, भले ही मेथड को सबक्लासेस में ओवरराइड किया गया हो। ऐसा करने का एक तरीका ऑब्जेक्ट के सिंगलटन क्लास में एक मॉड्यूल जोड़ना है।
module Logging
def make_noise
puts "Started making noise"
super
puts "Finished making noise"
end
end
class Bird
def make_noise
puts "Chirp, chirp!"
end
end
object = Bird.new
object.singleton_class.include(Logging)
object.make_noise
# Started making noise
# Chirp, chirp!
# Finished making noise
इस उदाहरण में, Bird.new का उपयोग करके एक Bird ऑब्जेक्ट बनाया जाता है, और परिणामी ऑब्जेक्ट में इसके सिंगलटन क्लास का उपयोग करके Logging मॉड्यूल शामिल किया जाता है।
सिंगलटन क्लास क्या है?
रूबी उन मेथड्स की अनुमति देती है जो एक सिंगल ऑब्जेक्ट के लिए अद्वितीय हैं। इसका समर्थन करने के लिए, रूबी ऑब्जेक्ट और उसकी वास्तविक क्लास के बीच एक अनाम क्लास जोड़ती है। जब मेथड्स को कॉल किया जाता है, तो सिंगलटन क्लास पर परिभाषित मेथड्स को वास्तविक क्लास में मेथड्स पर प्राथमिकता मिलती है। ये सिंगलटन क्लासेस हर ऑब्जेक्ट के लिए अद्वितीय हैं, इसलिए उनमें मेथड्स जोड़ने से वास्तविक क्लास के किसी अन्य ऑब्जेक्ट पर प्रभाव नहीं पड़ता। क्लासेस और ऑब्जेक्ट्स के बारे में प्रोग्रामिंग रूबी गाइड में और जानें।
हर बार ऑब्जेक्ट बनने पर उसके सिंगलटन क्लास को संशोधित करना थोड़ा बोझिल है। तो आइए Logging क्लास के समावेश को इनिशियलाइज़र में ले जाएं ताकि यह हर बनाए गए ऑब्जेक्ट के लिए जुड़ जाए।
module Logging
def make_noise
puts "Started making noise"
super
puts "Finished making noise"
end
end
class Bird
def initialize
singleton_class.include(Logging)
end
def make_noise
puts "Chirp, chirp!"
end
end
object = Bird.new
object.make_noise
# Started making noise
# Chirp, chirp!
# Finished making noise
यह अच्छा काम करता है, लेकिन अगर हम Bird की एक सबक्लास बनाते हैं, जैसे Duck, तो इसके इनिशियलाइज़र को Logging व्यवहार को बनाए रखने के लिए super कॉल करना होगा। जबकि कोई तर्क दे सकता है कि जब भी कोई मेथड ओवरराइड किया जाता है तो super को ठीक से कॉल करना हमेशा एक अच्छा विचार है, आइए एक ऐसा तरीका खोजने की कोशिश करते हैं जिसमें इसकी आवश्यकता न हो।
अगर हम सबक्लास से super कॉल नहीं करते हैं, तो हम Logger क्लास के समावेश को खो देते हैं:
class Duck < Bird
def initialize(name)
@name = name
end
def make_noise
puts "#{@name}: Quack, quack!"
end
end
object = Duck.new('Felix')
object.make_noise
# Felix: Quack, quack!
इसके बजाय, आइए Bird.new को ओवरराइड करें। जैसा कि पहले उल्लेख किया गया है, new क्लासेस पर कार्यान्वित सिर्फ एक मेथड है। तो हम इसे ओवरराइड कर सकते हैं, super कॉल कर सकते हैं, और नव निर्मित ऑब्जेक्ट को अपनी आवश्यकताओं के अनुसार संशोधित कर सकते हैं।
class Bird
def self.new(*arguments, &block)
instance = super
instance.singleton_class.include(Logging)
instance
end
end
object = Duck.new('Felix')
object.make_noise
# Started making noise
# Felix: Quack, quack!
# Finished making noise
लेकिन, क्या होता है जब हम इनिशियलाइज़र में make_noise कॉल करते हैं? दुर्भाग्य से, क्योंकि सिंगलटन क्लास में अभी तक Logging मॉड्यूल शामिल नहीं है, हमें वांछित आउटपुट नहीं मिलेगा।
सौभाग्य से, एक समाधान है: डिफ़ॉल्ट .new व्यवहार को स्क्रैच से बनाना allocate को कॉल करके संभव है।
class Bird
def self.new(*arguments, &block)
instance = allocate
instance.singleton_class.include(Logging)
instance.send(:initialize, *arguments, &block)
instance
end
end
allocate को कॉल करने से क्लास का एक नया, अनइनिशियलाइज़्ड ऑब्जेक्ट लौटता है। तो बाद में, हम अतिरिक्त व्यवहार शामिल कर सकते हैं और केवल तब, उस ऑब्जेक्ट पर initialize मेथड को कॉल करें। (क्योंकि initialize डिफ़ॉल्ट रूप से प्राइवेट है, हमें इसके लिए send का सहारा लेना होगा)।
Class#allocate के बारे में सच्चाई
अन्य मेथड्स के विपरीत, allocate को ओवरराइड करना संभव नहीं है। रूबी आंतरिक रूप से allocate के लिए मेथड्स को डिस्पैच करने के पारंपरिक तरीके का उपयोग नहीं करता है। परिणामस्वरूप, new को ओवरराइड किए बिना सिर्फ allocate को ओवरराइड करना काम नहीं करता। हालांकि, अगर हम allocate को सीधे कॉल कर रहे हैं, तो रूबी पुनर्परिभाषित मेथड को कॉल करेगा। रूबी के डॉक्यूमेंटेशन में Class#new और Class#allocate के बारे में और जानें।
हम ऐसा क्यों करेंगे?
बहुत सी चीजों की तरह, रूबी द्वारा क्लासेस से ऑब्जेक्ट्स बनाने के तरीके को संशोधित करना खतरनाक हो सकता है और चीजें अप्रत्याशित तरीके से टूट सकती हैं।
फिर भी, ऑब्जेक्ट निर्माण को बदलने के लिए वैध उपयोग के मामले हैं। उदाहरण के लिए, एक्टिवरिकॉर्ड डेटाबेस से ऑब्जेक्ट्स बनाते समय अनसेव्ड ऑब्जेक्ट्स बनाने के विपरीत इनिशियलाइज़ेशन प्रक्रिया को बदलने के लिए एक अलग init_from_db मेथड के साथ allocate का उपयोग करता है। यह becomes के साथ विभिन्न सिंगल-टेबल इनहेरिटेंस टाइप्स के बीच रिकॉर्ड्स को कन्वर्ट करने के लिए allocate का भी उपयोग करता है।
सबसे महत्वपूर्ण, ऑब्जेक्ट निर्माण के साथ खेलकर, आपको रूबी में इसके काम करने के तरीके में गहरी अंतर्दृष्टि मिलती है और अपने दिमाग को विभिन्न समाधानों के लिए खोलते हैं। हमें उम्मीद है कि आपको लेख पसंद आया।
हम रूबी के ऑब्जेक्ट्स बनाने के डिफ़ॉल्ट तरीके को बदलकर आपके द्वारा कार्यान्वित चीजों के बारे में सुनना पसंद करेंगे। कृपया @AppSignal पर अपने विचार ट्वीट करने में संकोच न करें।