2012-11-03 46 views
6

मैं कक्षा पुस्तकालय विकसित कर रहा हूं।अपरिवर्तनीय कक्षाओं के लिए क्लोन() लागू करना

  1. मेरे पास matrices के लिए एक सार बेस क्लास मैट्रिक्स है जो कुछ बुनियादी तरीकों के लिए कार्यान्वयन प्रदान करता है।
  2. मैट्रिक्स से व्युत्पन्न विभिन्न प्रकार के मैट्रिस के लिए ठोस उप-वर्ग हैं।
  3. मैट्रिक्स के लिए क्लोन करने योग्य होने की आवश्यकता है, इसलिए मैट्रिक्स क्लोनेबल इंटरफ़ेस लागू करता है।
  4. मैट्रिक्स से व्युत्पन्न वर्ग के कुछ अपरिवर्तनीय हैं

यह अपरिवर्तनीय वर्गों 'क्लोन तरीकों कि बजाय वस्तु का क्लोन लौटने का, वस्तु ही दिया जाता है के लिए स्वीकार्य होगा?

कुछ (oversimplified) स्पष्टीकरण के लिए कोड:

abstract class Matrix implements Cloneable { 
    ... 
} 

class ImmutableMatrix extends Matrix { 
    ImmutableMatrix clone() { 
     return this; 
    } 
    ... 
} 

class SomeOtherMatrix extends Matrix { 
    SomeOtherMatrix clone() { 
     SomeOtherMatrix other = super.clone(); 
     ... 
     return other; 
    } 
    ... 
} 
+0

क्यों आपकी ऑब्जेक्ट्स को पहले स्थान पर क्लोन करने की इजाजत दी गई है? –

+1

मूल संचालन के चारों ओर एक छोटे से आवरण को वापस करके और फ्लाई पर मूल्यों की गणना करके कुछ संचालन (जैसे पारदर्शिता) को आसानी से कार्यान्वित किया जा सकता है। इसके अलावा, आप कुछ परिस्थितियों में स्मृति पदचिह्न को कम कर सकते हैं (यानी बड़े स्पैस मैट्रिस पर संचालन)। यह तब तक ठीक काम करता है जब तक मूल मैट्रिक्स अपरिवर्तनीय न हो। अन्यथा मूल मैट्रिक्स में किए गए किसी भी बदलाव के परिणामस्वरूप दुष्प्रभाव होंगे। लेकिन अब मैंने इसे प्राप्त करने योग्य() विधि प्रदान करके हल किया है कि अपरिवर्तनीय उप-वर्गों के लिए केवल ऑब्जेक्ट स्वयं ही लौटाता है, जबकि उत्परिवर्तनीय उप-वर्ग एक अपरिवर्तनीय प्रतिलिपि लौटाते हैं। और क्लोनिंग नहीं। – Axel

उत्तर

8

मैं super.clone() बुला पर्याप्त होगा सोचा होगा।

यदि आपकी कक्षा अपरिवर्तनीय है तो इसे पहले से ही किसी भी उत्परिवर्तनीय वर्गों को क्लोन किया जाना चाहिए था जब इसे बनाया गया था। इसलिए मुझे लगता है कि आपकी कक्षा के किसी भी क्षेत्र की उथली प्रतियां सुरक्षित रहेंगी।

जावाडॉक्स राज्य x.clone() != x को प्राथमिकता दी जाती है। हालांकि यह एक पूर्ण आवश्यकता नहीं है, यह निश्चित रूप से this वापस करने के लिए आपकी योजना द्वारा उल्लंघन किया जाएगा।

-1

हाँ यदि हम स्ट्रिंग (अपरिवर्तनीय वर्ग) के व्यवहार को देखते हैं, यदि सामग्री समान है तो वही वस्तु वापस आती है, इसलिए मुझे लगता है कि आप सही हैं, क्लोन() विधि केवल इसे वापस करनी चाहिए।

+1

लेकिन स्ट्रिंग क्लोन करने योग्य नहीं है। – Axel

+0

हां स्ट्रिंग क्लोन करने योग्य नहीं है, लेकिन स्मृति को सहेजने के लिए यदि दो ऑब्जेक्ट्स की सामग्री समान है और अपरिवर्तनीय है जो अन्य ऑब्जेक्ट्स बनाने के बजाए एक ही वस्तु को वापस करनी चाहिए – zaffargachal

+1

यही मैं भी सोच रहा था। अंत में मैंने कुछ अलग किया। मैट्रिक्स को क्लोनेबल लागू करने की आवश्यकता थी क्योंकि कुछ तरीकों को एक तर्क के रूप में पारित मैट्रिक्स की एक अपरिवर्तनीय प्रतिलिपि बनाना था। इसलिए मैंने उन विधियों के अंदर मैट्रिक्स तर्क को क्लोन किया। अब, मैंने मैट्रिक्स कक्षा में एक सार 'getImmutable() 'विधि जोड़ा और इसके बजाय इसका उपयोग किया। यह मुझे अपर्याप्त वर्गों के लिए अनावश्यक क्लोन बनाने से बचाता है जबकि उत्परिवर्तनीय कक्षाएं मैट्रिक्स की एक अपरिवर्तनीय प्रति बनाकर इस विधि के अपने कार्यान्वयन को प्रदान कर सकती हैं। – Axel

4

अपरिवर्तनीय कक्षाओं के क्लोन() कार्यान्वयन में बस this लौटें।

2

आप अपरिवर्तनीय कक्षाएं हो सकता था जबकि बस clone लागू खुद को संदर्भ वापस जाने के लिए, मैं वास्तव में चीजें हैं जो या परिवर्तनशील नहीं हो सकता पर clone का प्रयोग करने में ज्यादा मूल्य नहीं दिख रहा है, अपरिवर्तनीय की परिवर्तनशील copes बनाने का किसी तरह से अनुपस्थित चीजें और इसके विपरीत।

मैं इसे अपने आधार के लिए बेहतर Matrix वर्ग होगा तरीकों IsImmutable और IsWritable, AsImmutable, AsMutable, और AsNewMutable तरीकों के साथ शामिल करने के लिए लगता होगा; इसमें मैट्रिक्स को पढ़ने और लिखने के तरीकों को भी शामिल करना चाहिए (हालांकि गैर-लिखने योग्य मैट्रिक्स पर "लिखने" विधि को कॉल करना अपवाद फेंकना चाहिए)।

स्थिर तरीकों CreateImmutableMatrix और CreateMutableMatrix जो, एक Matrix दिया परिभाषित करें, एक नया अपरिवर्तनीय या परिवर्तनशील मैट्रिक्स जो उचित डेटा के साथ पहले से प्रारंभ है पैदा करेगा।

परिवर्त्य कक्षाएं AsImmutable लागू, CreateImmutableMatrix के लिए खुद को पारित करने के लिए AsMutable खुद को वापस जाने के लिए चाहिए, और AsNewMutable खुद को CreateMutableMatrix को पारित करने के लिए।

अपरिवर्तनीय कक्षाएं AsImmutable खुद को वापस जाने के लिए, AsMutableAsNewMutable कॉल करने के लिए लागू करना चाहिए, और AsNewMutable खुद को CreateMutableMatrix को पारित करने के लिए।

केवल-पढ़ने के रैपर AsImmutable लागू लिपटे वस्तुओं पर AsImmutable, और AsMutable और AsNewMutable कॉल करने के लिए लिपटे वस्तुओं पर AsNewMutable कॉल करने के लिए करना चाहिए।

एक ऑब्जेक्ट जो एक मैट्रिक्स प्राप्त करता है जिसे कॉपी या म्यूटेट करने की आवश्यकता हो सकती है या नहीं, इसे आसानी से किसी फ़ील्ड में संग्रहीत कर सकता है (उदा। Foo)। यदि इसे मैट्रिक्स को म्यूटेट करने की आवश्यकता है, तो यह Foo को Foo.AsMutable() के साथ प्रतिस्थापित कर सकता है। यदि मैट्रिक्स युक्त ऑब्जेक्ट की प्रतिलिपि बनाई जानी चाहिए, तो प्रतिलिपि को प्रतिस्थापित करने की आवश्यकता होने पर इस क्षेत्र को प्रतिलिपि में Foo.AsImmutable() या Foo.AsNewMutable() के साथ प्रतिस्थापित किया जाना चाहिए।

+0

आपके उत्तर के लिए धन्यवाद। उस दौरान मैंने जो समाधान लागू किया है, वह बहुत अच्छी तरह से वर्णन करता है। – Axel

+0

@supercat मैं एक मूल दृश्य इंटरफ़ेस के साथ अपरिवर्तनीय/परिवर्तनीय कक्षाओं के लिए एक समान योजना लागू कर रहा हूं (मैंने यह पोस्ट भी देखा: http://programmers.stackexchange.com/questions/221762/why-doesnt-java-8- शामिल करें- अपरिवर्तनीय-संग्रह)। मैं 'AsNewMutable' और' AsImutable 'विधियों का उद्देश्य देखता हूं, लेकिन मुझे' Asmutable 'के बारे में निश्चित नहीं है। एक म्यूटेबल ऑब्जेक्ट पर ऐसी विधि को कॉल नहीं करना इंगित करता है कि आपको उस ऑब्जेक्ट को इसके उत्परिवर्तनीय संस्करण के रूप में गुजरना चाहिए था ? किसी ऑब्जेक्ट पर इस विधि को कॉल करने का तात्पर्य है कि आपके पास दुष्प्रभाव हो सकते हैं या आप शायद नहीं कर सकते हैं। –

+1

@AlexanderKaratarakis: विचार यह होगा कि कोई संदर्भों पर 'AsMutable' को कॉल करेगा, जिसे या तो (1) अपरिवर्तनीय होने की गारंटी दी गई थी, या (2) ब्रह्मांड में केवल संदर्भ में म्यूटेबल ऑब्जेक्ट में एकमात्र संदर्भ है - सबसे अधिक संभावना है जिसे एक अपरिवर्तनीय वस्तु पर "AsMutable" को कॉल करके उत्पादित किया गया था और जिसे तब से साझा नहीं किया गया था।एक म्यूटेबल ऑब्जेक्ट के ब्रह्मांड के एकमात्र संदर्भ पर 'AsNewMutable' को कॉल करना काम करेगा, लेकिन यह अनावश्यक रूप से धीमा होगा। यदि कोड किसी ऑब्जेक्ट को क्लोन कर रहा है उदा। दस "महंगे" गुण, और यह संभावना है कि केवल एक या दो को पहले बदलना होगा ... – supercat

0

आपकी कक्षा सख्ती से अपरिवर्तनीय नहीं है क्योंकि यह अंतिम नहीं है: उत्परिवर्तनीय उप-वर्ग हो सकते हैं।

किसी ImmutableMatrix उपवर्ग करना चाहता है, वह नहीं super.clone() फोन करके clone() लागू करने में सक्षम है, तो आप सिर्फ this वापसी हो जाएगा। तो उस स्थिति में आपको super.clone() पर कॉल करना चाहिए।

हालांकि, यदि आप अपनी कक्षा को अंतिम बनाते हैं, तो मुझे कोई कारण नहीं दिख रहा है कि क्यों न केवल this लौटाएं।

+0

यदि वर्ग के लिए अनुबंध बताता है कि राज्य का कोई भी पहलू कभी भी नहीं बदला जाएगा, तो कोई उप-वर्ग जो उल्लंघन करता है वह टूटा हुआ है। भले ही यह किसी भी * विरासत योग्य वर्ग के लिए लगभग कभी भी संभव नहीं है, यह गारंटी देने के लिए कि सबक्लास अपने अनुबंध का पालन करेंगे, सामान्य अभ्यास गैर-सुरक्षा-संबंधित संदर्भों में मानना ​​है जो कक्षाएं प्राप्त की जाती हैं। क्या यह सामान्य अभ्यास नहीं था, विरासत बहुत बेकार होगी। मुझे उस संबंध में किसी भी अन्य संविदात्मक वचन से मौलिक रूप से अलग होने के कारण अपरिवर्तनीयता का सम्मान करने का कोई कारण नहीं दिखता है। – supercat

+0

@ सुपरस्कैस अपरिवर्तनीय है, भले ही सुपरक्लोन() – WilQu

+0

पर कॉल करके क्लोन को कार्यान्वित कर सकता है यदि सबक्लास अपरिवर्तनीय है, भले ही बेस क्लास के सभी डेरिवेटिव न हों, तो यह 'रिटर्न' को केवल 'रिटर्न' द्वारा लागू कर सकता है इस; '। यदि वर्ग * अनुबंध द्वारा निर्दिष्ट * अपरिवर्तनीय होने के लिए, 'क्लोन' को लागू करने के रूप में लागू करने के लिए स्वीकार्य हो सकता है, भले ही कक्षा विरासत योग्य हो, भले ही अनुबंध * दस्तावेज * जो व्युत्पन्न कक्षाएं वैध रूप से कुछ भी नहीं करेगी जो क्लोन होगा अलग होना – supercat