रूबी को महान बनाने वाली चीजों में से एक यह है कि हम अपनी जरूरतों के लिए लगभग कुछ भी अनुकूलित कर सकते हैं। यह उपयोगी और खतरनाक दोनों है। अपने आप को पैर में गोली मारना आसान है, लेकिन जब सावधानी से उपयोग किया जाता है, तो इसका परिणाम बहुत शक्तिशाली समाधान हो सकता है।
रूबी मैजिक में, हमें लगता है कि उपयोगी और खतरनाक एक उत्कृष्ट संयोजन है। आइए देखें कि रूबी वस्तुओं को कैसे बनाता है और आरंभ करता है और हम डिफ़ॉल्ट व्यवहार को कैसे संशोधित कर सकते हैं।
कक्षाओं से नई वस्तुएँ बनाने की मूल बातें
आरंभ करने के लिए, आइए देखें कि रूबी में ऑब्जेक्ट कैसे बनाएं। एक नया ऑब्जेक्ट बनाने के लिए (या उदाहरण ), हम 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
ऑब्जेक्ट Bird.new
. का उपयोग करके बनाया गया है , और 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
, इसके प्रारंभकर्ता को super
. को कॉल करने की आवश्यकता है Logging
को बनाए रखने के लिए व्यवहार। जबकि कोई यह तर्क दे सकता है कि 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
कक्षाओं पर लागू सिर्फ एक विधि है। इसलिए हम इसे ओवरराइड कर सकते हैं, सुपर को कॉल कर सकते हैं, और नई बनाई गई वस्तु को अपनी आवश्यकताओं के अनुसार संशोधित कर सकते हैं।
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
. के लिए प्रेषण विधियों के पारंपरिक तरीके का उपयोग नहीं करती है आंतरिक रूप से। परिणामस्वरूप, बस ओवरराइड करना allocate
बिना ओवरराइड किए new
काम नहीं करता। हालांकि, अगर हम allocate
को कॉल कर रहे हैं सीधे, रूबी पुनर्निर्धारित विधि को कॉल करेगी। Class#new
के बारे में अधिक जानें और Class#allocate
रूबी के दस्तावेज़ीकरण में।
हम ऐसा क्यों करेंगे?
बहुत सी चीजों की तरह, रूबी द्वारा कक्षाओं से वस्तुओं को बनाने के तरीके को संशोधित करना खतरनाक हो सकता है और चीजें अप्रत्याशित तरीके से टूट सकती हैं।
फिर भी, वस्तु निर्माण को बदलने के लिए वैध उपयोग के मामले हैं। उदाहरण के लिए, ActiveRecord allocate
. का उपयोग करता है एक अलग init_from_db
. के साथ सहेजे नहीं गए ऑब्जेक्ट्स के निर्माण के विरोध में डेटाबेस से ऑब्जेक्ट बनाते समय प्रारंभिक प्रक्रिया को बदलने की विधि। यह allocate
. का भी उपयोग करता है becomes
. के साथ अलग-अलग सिंगल-टेबल इनहेरिटेंस प्रकारों के बीच रिकॉर्ड्स को कन्वर्ट करने के लिए ।
सबसे महत्वपूर्ण, वस्तु निर्माण के साथ खिलवाड़ करके, आप रूबी में कैसे काम करते हैं, इसकी गहरी जानकारी प्राप्त करते हैं और अपने दिमाग को विभिन्न समाधानों के लिए खोलते हैं। हमें उम्मीद है कि आपको लेख अच्छा लगा होगा।
रूबी के ऑब्जेक्ट बनाने के डिफ़ॉल्ट तरीके को बदलकर आपके द्वारा कार्यान्वित की गई चीजों के बारे में सुनना हमें अच्छा लगेगा। कृपया अपने विचार @AppSignal पर ट्वीट करने में संकोच न करें।