2013-04-03 5 views
6

मैं बहुरूपी क्लोनिंग (गहरी प्रतिलिपि) के साथ मेरी कक्षा से लैस करने की जरूरत है, यानी मैं काम करने के लिए कुछ इस तरह की जरूरत है:क्या जावा क्लोन() विधि पॉलिमॉर्फिक क्लोनिंग प्राप्त करने का एकमात्र तरीका है?

SuperType original = new SubType(); 
SuperType copy = original.clone(); 

जहां original.clone() किसी भी तंत्र द्वारा प्रतिस्थापित किया जा सकता है एक गहरी प्रतिलिपि बनाने के लिए, और वास्तविक प्रकार copySubType होगा, क्योंकि original भी SubType है।

clone() विधि और Cloneable इंटरफ़ेस इसे प्राप्त करने का एकमात्र तरीका है? फैक्ट्री विधियों और कॉपी कन्स्ट्रक्टर का उपयोग नहीं किया जा सकता है, क्योंकि वास्तविक वर्ग केवल रन टाइम में ही जाना जाता है, है ना? क्या उन धारावाहिक-deserialize दृष्टिकोण को छोड़कर कोई अन्य सुझाए गए तरीके हैं, और Java deep-cloning library जो clone() विधि से IMHO भी बदतर काला जादू है?

धन्यवाद, पेट्र

+0

आप एक रचनाकार नहीं बना सकते हैं कि जिस वस्तु को आप क्लोन करना चाहते हैं उसे पास किया जा सकता है? – Justin

+0

@gangqinlaohu निश्चित रूप से, मैं कर सकता हूं, लेकिन फिर मुझे 'नया सबटाइप (मूल)' कॉल करने की आवश्यकता होगी, क्योंकि मैं कोड लिखने के समय में नहीं जानता क्योंकि मूल वास्तव में वर्ग 'सबटाइप' या 'सबटाइप 2' , या 'सबसब टाइप'। – Posa

उत्तर

4

असल में ऑब्जेक्ट की clone() विधि आपको कोई पॉलिमॉर्फिक कॉल करने की अनुमति नहीं दे रही है क्योंकि protected है। कार्यान्वित Cloneable कोई उपयोग नहीं है क्योंकि इसमें clone() विधि नहीं है।

आप क्लोन क्लास के लिए पॉलिमॉर्फिक विधि प्रदान करके पॉलिमॉर्फिक क्लोनिंग कर सकते हैं जो बदले में कॉपी कन्स्ट्रक्टर का आह्वान करता है। अपने कोड काम करने के लिए

Joshua Block's opinion on cloning vs. copy constructor

+0

ठीक है, यह काम करेगा। लेकिन 'क्लोन()' का उपयोग करने से यह किस मायने में अलग है? क्या 'deepCopy()' विधि इसके लिए सिर्फ एक अलग नाम नहीं है? क्या आप 'गहरी चोटी()' में क्लोन() 'में किए गए वही काम नहीं कर सकते हैं? – Posa

+0

@ पोसा क्लोनिंग एक जावा "निर्मित" तरीका है जो प्रतिलिपि बनाने की आवश्यकता के बिना ऑब्जेक्ट प्रतियां प्रदान करने के लिए है। इसने प्रोग्रामर को जीवन आसान बनाने का प्रयास किया, लेकिन आईएमओ यह मामला नहीं है। हां, अगर आप क्लोन() '(जोशुआ ब्लॉक के इफेक्टिव जावा के बारे में एक संपूर्ण अध्याय है) को ओवरराइड करते समय बहुत सावधानी बरतते हैं, तो आपको एक ही परिणाम मिलना चाहिए। – dcernahoschi

1

आप बस आप Cloneable इंटरफेस पसंद नहीं है सभी उपप्रकार

class SuperType { 

    public SuperType copy() { 
       ... 
    } 
} 
0

में महाप्रकार और इसे लागू करने के एक प्रति विधि जोड़ सकते हैं, आप अपने खुद इंटरफ़ेस बना सकते हैं। प्रत्येक वर्ग सही प्रकार का एक नया उदाहरण बनाने के लिए जिम्मेदार होगा।

+0

यह इस तथ्य के बारे में नहीं है कि मुझे 'क्लोनबल' पसंद नहीं है। मैं डॉन-यूज-क्लोन पैनिक को समझ नहीं पा रहा हूं (शायद मुझे जे क्लॉच की पुस्तक पढ़ने के बावजूद 'क्लोन' से संबंधित जारी नहीं समझा जाता है)। 'क्लोनबल' के समान उद्देश्य के लिए मूल रूप से अपना इंटरफ़ेस क्यों तैयार करेगा? या मेरे अपने इंटरफेस का उद्देश्य 'क्लोनबल' से अलग होगा? – Posa

+0

ठीक है, आपका सवाल था "क्या क्लोन() विधि और क्लोनेबल इंटरफ़ेस इसे प्राप्त करने का एकमात्र तरीका है?"। यदि क्लोन() विधि आपके लिए ठीक है, तो इसका इस्तेमाल करें। हालांकि, एक कस्टम इंटरफेस का उपयोग करने से आप जेनेरिक का लाभ उठा सकते हैं। – WilQu

2

के लिए, कि कोड है या तो SuperType वर्ग या उपवर्ग, या अपने SuperType प्रकार के अंदर एक सार्वजनिक clone() विधि होनी चाहिए:

abstract class SuperType { 
    public SuperType(SuperType t) { 
    } 

    public abstract SuperType deepCopy(); 
} 

class SomeType extends SuperType { 

    SomeType(SomeType t) { 
     //copy constructor 
    } 

    @Override 
    public SomeType deepCopy() {       
     return new SomeType(this); 
    } 
} 

... 

SuperType original = new SubType(); 
SuperType copy = original.deepCopy(); //the deepCopy is called on children classes 

भी देखें। एक सार्वजनिक clone() विधि स्वचालित रूप से मौजूद नहीं है, और आपको इसे लागू करना होगा। आप उस मामले के लिए इसे और कुछ भी कह सकते हैं, उदा। copy()

आपका प्रश्न तब है, clone() (या जिसे आप इसे कहते हैं) विधि को कार्यान्वित करना है ताकि यह पॉलिमॉर्फिक क्लोनिंग कर सके।

जावा डेवलपर्स द्वारा लक्षित किया गया तरीका super.clone() पर कॉल करना है, यह मानते हुए कि विरासत पदानुक्रम में सभी वर्गों ने समान रूप से clone() को पॉलिमॉर्फिक क्लोनिंग करने के लिए लागू किया है। यह अंततः सुरक्षित Object.clone() विधि तक पहुंच जाता है, जो पॉलिमॉर्फिक क्लोनिंग का जादू करता है। ध्यान दें कि अपवाद फेंकने के लिए Object.clone() के लिए, आपकी कक्षा को Cloneable इंटरफ़ेस लागू करना होगा।

हालांकि, अन्य संभावित तरीके भी हैं। उदाहरण के लिए, यह मानते हुए कि सभी उप-वर्गों में एक डिफ़ॉल्ट कन्स्ट्रक्टर है, आप this.getClass().newInstance() जैसे कुछ कर सकते हैं। यह सही वर्ग का एक वस्तु बना देगा, लेकिन खेतों की प्रतिलिपि बनाई गई नहीं है। आपके क्लोन विधि को सभी फ़ील्ड कॉपी करने की आवश्यकता होगी, और उप-वर्गों को अपने क्लोन विधि को अपने फ़ील्ड की प्रतिलिपि बनाने के लिए ओवरराइड करना होगा। ध्यान दें कि यह अप्रासंगिक है कि Cloneable इंटरफ़ेस इस मामले में लागू किया गया है या नहीं।

एक और तरीका यह सोचते हैं कि वर्ग Serializable है, को क्रमानुसार और this unserialize करने के लिए, है। यह एक बहुलक क्लोन बनाना चाहिए जिसमें सभी धारावाहिक खेतों को पूरा किया जाए।

संबंधित मुद्दे