आप रूबी में प्रोटोटाइप-आधारित प्रोग्रामिंग करने के लिए क्लोन का उपयोग कर सकते हैं। रूबी का ऑब्जेक्ट क्लास क्लोन विधि और डुप विधि दोनों को परिभाषित करता है। क्लोन और डुप दोनों ही उस वस्तु की एक उथली प्रतिलिपि का उत्पादन करते हैं जो इसे कॉपी कर रहा है; वह है, ऑब्जेक्ट के उदाहरण चर कॉपी किए जाते हैं, लेकिन वे ऑब्जेक्ट नहीं जो वे संदर्भ देते हैं। मैं एक उदाहरण प्रदर्शित करूंगा:
class Apple
attr_accessor :color
def initialize
@color = 'red'
end
end
apple = Apple.new
apple.color
=> "red"
orange = apple.clone
orange.color
=> "red"
orange.color << ' orange'
=> "red orange"
apple.color
=> "red orange"
उपरोक्त उदाहरण में नोटिस, नारंगी क्लोन सेब ऑब्जेक्ट की स्थिति (यानी, उदाहरण चर) को कॉपी करता है, लेकिन जहां सेब ऑब्जेक्ट अन्य ऑब्जेक्ट (जैसे स्ट्रिंग ऑब्जेक्ट रंग) का संदर्भ देता है, उन संदर्भों की प्रतिलिपि नहीं बनाई जाती है। इसके बजाय, सेब और नारंगी दोनों एक ही वस्तु को संदर्भित करते हैं! हमारे उदाहरण में, संदर्भ स्ट्रिंग ऑब्जेक्ट 'रेड' है। जब नारंगी एपेंड विधि का उपयोग करता है, <<, मौजूदा स्ट्रिंग ऑब्जेक्ट को संशोधित करने के लिए, यह स्ट्रिंग ऑब्जेक्ट को 'रेड ऑरेंज' में बदलता है। यह प्रभाव Apple.color में भी परिवर्तन करता है, क्योंकि वे दोनों एक ही स्ट्रिंग ऑब्जेक्ट की ओर इशारा कर रहे हैं।
एक साइड नोट के रूप में, असाइनमेंट ऑपरेटर, =, एक नई ऑब्जेक्ट असाइन करेगा और इस तरह एक संदर्भ को नष्ट कर देगा। यहाँ एक प्रदर्शन है:
class Apple
attr_accessor :color
def initialize
@color = 'red'
end
end
apple = Apple.new
apple.color
=> "red"
orange = apple.clone
orange.color
=> "red"
orange.color = 'orange'
orange.color
=> 'orange'
apple.color
=> 'red'
उपरोक्त उदाहरण में, जब हमने नारंगी क्लोन के रंग उदाहरण विधि के लिए एक नई नई वस्तु सौंपी, तो यह सेब के समान वस्तु का संदर्भ नहीं देता है। इसलिए, हम अब सेब की रंग विधि को प्रभावित किए बिना नारंगी के रंग विधि को संशोधित कर सकते हैं, लेकिन अगर हम सेब से किसी अन्य ऑब्जेक्ट को क्लोन करते हैं, तो वह नई वस्तु सेब के रूप में कॉपी किए गए उदाहरण चर में समान वस्तुओं को संदर्भित करेगी।
डुप भी उस ऑब्जेक्ट की एक उथली प्रतिलिपि का उत्पादन करेगा जो वह कॉपी कर रहा है, और यदि आप उसी प्रदर्शन को करने के लिए ऊपर दिखाए गए थे, तो आप देखेंगे कि यह ठीक उसी तरह से काम करता है। लेकिन क्लोन और डुप के बीच दो प्रमुख अंतर हैं। सबसे पहले, जैसा कि दूसरों ने उल्लेख किया है, क्लोन जमे हुए राज्य की नकल करता है और डुबकी नहीं करता है। इसका क्या मतलब है? रूबी में 'फ्रोजन' शब्द अपरिवर्तनीय के लिए एक गूढ़ शब्द है, जो खुद कंप्यूटर विज्ञान में एक नामकरण है, जिसका अर्थ है कि कुछ बदला नहीं जा सकता है। इस प्रकार, रूबी में एक जमे हुए ऑब्जेक्ट को किसी भी तरह से संशोधित नहीं किया जा सकता है; यह वास्तव में, अपरिवर्तनीय है। यदि आप एक जमे हुए ऑब्जेक्ट को संशोधित करने का प्रयास करते हैं, तो रूबी एक रनटाइम एट्रस अपवाद को बढ़ाएगा। चूंकि क्लोन जमे हुए राज्य को कॉपी करता है, यदि आप एक क्लोन ऑब्जेक्ट को संशोधित करने का प्रयास करते हैं, तो यह एक रनटाइम एट्रस्ट अपवाद को बढ़ाएगा। इसके विपरीत, चूंकि डुबकी जमे हुए राज्य की नकल नहीं करती है,
class Apple
attr_accessor :color
def initialize
@color = 'red'
end
end
apple = Apple.new
apple.frozen?
=> false
apple.freeze
apple.frozen?
=> true
apple.color = 'crimson'
RuntimeError: can't modify frozen Apple
apple.color << ' crimson'
=> "red crimson" # we cannot modify the state of the object, but we can certainly modify objects it is referencing!
orange = apple.dup
orange.frozen?
=> false
orange2 = apple.clone
orange2.frozen?
=> true
orange.color = 'orange'
=> "orange" # we can modify the orange object since we used dup, which did not copy the frozen state
orange2.color = 'orange'
RuntimeError: can't modify frozen Apple # orange2 raises an exception since the frozen state was copied via clone
दूसरा, और, अधिक दिलचस्प बात यह है कि क्लोन एकल वर्ग (और इसलिए इसके तरीके) की नकल करता है! यह बहुत उपयोगी है अगर आप रूबी में प्रोटोटाइप-आधारित प्रोग्रामिंग करना चाहते हैं। पहले, आइए दिखाते हैं कि वास्तव में सिंगलटन विधियों को क्लोन के साथ कॉपी किया जाता है, और फिर हम इसे रूबी में प्रोटोटाइप-आधारित प्रोग्रामिंग के एक उदाहरण में लागू कर सकते हैं।
class Fruit
attr_accessor :origin
def initialize
@origin = :plant
end
end
fruit = Fruit.new
=> #<Fruit:0x007fc9e2a49260 @origin=:plant>
def fruit.seeded?
true
end
2.4.1 :013 > fruit.singleton_methods
=> [:seeded?]
apple = fruit.clone
=> #<Fruit:0x007fc9e2a19a10 @origin=:plant>
apple.seeded?
=> true
जैसा कि आप देख सकते हैं, फल वस्तु उदाहरण के सिंगलटन वर्ग को क्लोन में कॉपी किया गया है। और इसलिए क्लोन किए गए ऑब्जेक्ट का सिंगलटन विधि तक पहुंच है: वरीयता प्राप्त। लेकिन यह मामला नहीं है:
apple = fruit.dup
=> #<Fruit:0x007fdafe0c6558 @origin=:plant>
apple.seeded?
=> NoMethodError: undefined method `seeded?'
अब प्रोटोटाइप-आधारित प्रोग्रामिंग में, आपके पास ऐसी कक्षाएं नहीं हैं जो अन्य कक्षाओं का विस्तार करती हैं और फिर उन कक्षाओं का उदाहरण बनाती हैं, जिनके तरीके एक मूल श्रेणी से प्राप्त होते हैं जो एक खाका के रूप में कार्य करता है। इसके बजाय, आपके पास एक आधार ऑब्जेक्ट है और फिर आप ऑब्जेक्ट से एक नई वस्तु बनाते हैं, जिसके तरीकों और राज्य की नकल की जाती है (बेशक, चूंकि हम क्लोन के माध्यम से उथली प्रतियां कर रहे हैं, किसी भी ऑब्जेक्ट का उदाहरण चर संदर्भ जावास्क्रिप्ट में ही साझा किया जाएगा। प्रोटोटाइप)। फिर आप क्लोन किए गए तरीकों के विवरण को भरकर ऑब्जेक्ट की स्थिति को भर सकते हैं या बदल सकते हैं। नीचे दिए गए उदाहरण में, हमारे पास आधार फल वस्तु है। सभी फलों में बीज होते हैं, इसलिए हम एक तरीका बनाते हैं नंबर_ऑफ_सेड्स। लेकिन सेब में एक बीज होता है, और इसलिए हम एक क्लोन बनाते हैं और विवरण भरते हैं। अब जब हम सेब का क्लोन बनाते हैं, तो हम न केवल तरीकों का क्लोन बनाते हैं, बल्कि हम राज्य का क्लोन बनाते हैं! याद रखें क्लोन राज्य की एक उथली प्रतिलिपि (उदाहरण चर) है। और उसके कारण, जब हम एक लाल_प्पल पाने के लिए सेब को क्लोन करते हैं, तो red_apple में स्वचालित रूप से 1 बीज होगा! आप Red_apple को Apple से विरासत में मिली हुई वस्तु के रूप में सोच सकते हैं, जो फल से विरासत में मिली है। इसलिए, यही कारण है कि मैंने फ्रूट और एप्पल को कैपिटल किया। हमने कक्षाओं और वस्तुओं के बीच के अंतर को क्लोन के सौजन्य से दूर किया।
Fruit = Object.new
def Fruit.number_of_seeds=(number_of_seeds)
@number_of_seeds = number_of_seeds
end
def Fruit.number_of_seeds
@number_of_seeds
end
Apple = Fruit.clone
=> #<Object:0x007fb1d78165d8>
Apple.number_of_seeds = 1
Apple.number_of_seeds
=> 1
red_apple = Apple.clone
=> #<Object:0x007fb1d892ac20 @number_of_seeds=1>
red_apple.number_of_seeds
=> 1
बेशक, हमारे पास प्रोटॉयपे-आधारित प्रोग्रामिंग में एक निर्माता विधि हो सकती है:
Fruit = Object.new
def Fruit.number_of_seeds=(number_of_seeds)
@number_of_seeds = number_of_seeds
end
def Fruit.number_of_seeds
@number_of_seeds
end
def Fruit.init(number_of_seeds)
fruit_clone = clone
fruit_clone.number_of_seeds = number_of_seeds
fruit_clone
end
Apple = Fruit.init(1)
=> #<Object:0x007fcd2a137f78 @number_of_seeds=1>
red_apple = Apple.clone
=> #<Object:0x007fcd2a1271c8 @number_of_seeds=1>
red_apple.number_of_seeds
=> 1
अंततः, क्लोन का उपयोग करके, आप जावास्क्रिप्ट प्रोटोटाइप व्यवहार के समान कुछ प्राप्त कर सकते हैं।
dup
और क्याclone
करता है, में अंतर नहीं जानता , लेकिन आप एक के बजाय दूसरे का उपयोग क्यों करेंगे।