2012-08-14 20 views
9

मेरे पास Pointer कक्षा है जो एकल गुण :contents है, जो कक्षा MyObject की किसी ऑब्जेक्ट को इंगित करती है।इसके उदाहरणों के लिए डुप्ली/क्लोन प्रदान करने के लिए रूबी क्लास को परिभाषित करने के लिए कौन सी विधि?

class MyObject 
    def hello; "hello" end 
end 

class Pointer 
    attr_reader :contents 
    def initialize(cont); @contents = cont end 
    # perhaps define some more state 
end 

मैं अपने Pointer स्वयं की प्रतियां बनाने के लिए सक्षम होना चाहता हूँ। मुझे पता है कि #dup विधि डिफ़ॉल्ट रूप से परिभाषित की गई है, जबकि #clone गहरी प्रतियां बनाने में सक्षम होने के लिए विधि को ओवरराइड होने की उम्मीद है। लेकिन यहां, प्रतियों को बहुत गहरा होना जरूरी नहीं है। तो, मेरे पास पहली दुविधा है, क्या मुझे #dup विधि ओवरराइड करना चाहिए, क्योंकि मैं वास्तव में अपने Pointer की अतिरिक्त स्थिति की प्रतिलिपि बनाना नहीं चाहता हूं, बस एक नया MyObject उदाहरण पर इंगित करें? या मुझे ओवरराइडिन #dup से बचना चाहिए, क्योंकि मुझे "माना जाना" नहीं है और #clone को विधि बनाने वाली विधि के साथ ओवरराइड करना है?

मैं उपर्युक्त टिप्पणियों का स्वागत करता हूं, लेकिन मान लें कि मैं #dup को ओवरराइड करना चुनूंगा। मैं तो बस ऐसा कर सकता है:

class Pointer 
    def dup; self.class.new(contents) end 
end 

लेकिन ऑनलाइन, मैं की तरह "dup विधि कॉल करेंगे प्रारंभ कॉपी विधि" कुछ पढ़ा। इसके अलावा, this guy रुबी में #initialize_clone, #initialize_dup और #initialize_copy लिखता है। इससे मुझे आश्चर्य होता है, शायद इस तरह का सबसे अच्छा अभ्यास है?

class Pointer 
    def initialize_copy 
    # do I don't know what 
    end 
end 

या इस तरह?

class Pointer 
    def initialize_dup 
    # do I don't know what 
    end 
end 

या मैं सिर्फ ऑनलाइन शुरुआती भ्रमित और चिंताओं के बिना #dup ओवरराइड करने के लिए जाने के लिए लिखा दोषारोपण के बारे में भूल जाना चाहिए?

इसके अलावा, मुझे समझ नहीं है कि मैं सिर्फ किसी भी कस्टम #dup को परिभाषित करने के बिना #dup कॉल कर सकते हैं, लेकिन क्या अगर मैं अलग व्यवहार के साथ #dup परिभाषित करना चाहते हैं?

इसके अलावा, एक ही प्रश्न #clone पर लागू होता है - क्या मुझे #initialize_clone या केवल #clone परिभाषित करने का प्रयास करना चाहिए?

+0

मैं पूछ सकता है कि आप एक सूचक वर्ग बिल्कुल बना रहे हैं ? रूबी के चर सभी पहले से ही संदर्भ/पॉइंटर्स हैं। –

+0

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

उत्तर

16

मेरे अनुभव से, #initialize_copy ओवरलोडिंग ठीक काम करता है (प्रारंभिक_डुप और प्रारंभिक_क्लोन के बारे में कभी नहीं सुना)।

मूल initialize_copy (जो मूल वस्तु से मूल्यों के साथ हर मामले चर initializes) सुपर माध्यम से उपलब्ध है, तो मैं आमतौर पर करते हैं:

class MyClass 
    def initialize_copy(orig) 
    super 
    # Do custom initialization for self 
    end 
end 
+0

#dup को फिर से परिभाषित करने के साथ इसकी तुलना कैसे की जाती है? क्या यह कभी ओ.के. है #dup को फिर से परिभाषित करने के लिए? –

+3

बड़ा अंतर यह है कि, जब आप #dup को फिर से परिभाषित करते हैं, तो 'स्वयं' मूल वस्तु है।इसलिए आपको नई ऑब्जेक्ट की आंतरिक स्थिति तक पहुंच नहीं है। यह #initialize_copy –

+2

में एक और तरीका है एक और अंतर: मैंने कठिन तरीका सीखा है कि, मैट्ज़ रूबी कार्यान्वयन में, कुछ सी फ़ंक्शंस कॉल उदा। सामान्य विधि प्रेषण का उपयोग करने के बजाय सीधे rb_obj_dup। #dup उनमें से एक हो सकता है। जिसका अर्थ यह है कि कुछ मानक लाइब्रेरी सामान * डू * आपके #dup के संस्करण को कॉल नहीं करेंगे, जबकि * #initialize_copy –