वह विशिष्ट कारण क्या है जिसे clone()
संरक्षित किया गया है java.lang.Object
?
वह विशिष्ट कारण क्या है जिसे clone()
संरक्षित किया गया है java.lang.Object
?
जवाबों:
तथ्य यह है कि क्लोन संरक्षित है बेहद संदिग्ध है - जैसा कि तथ्य यह है कि इंटरफ़ेस clone
में विधि घोषित नहीं की गई Cloneable
है।
यह डेटा की प्रतियां लेने के लिए विधि को बहुत बेकार बनाता है क्योंकि आप यह नहीं कह सकते :
if(a instanceof Cloneable) {
copy = ((Cloneable) a).clone();
}
मुझे लगता है कि डिजाइन Cloneable
अब काफी हद तक एक गलती के रूप में माना जाता है (नीचे उद्धरण)। मैं सामान्य रूप से एक इंटरफ़ेस का कार्यान्वयन करने में सक्षम होना चाहता हूं, Cloneable
लेकिन आवश्यक रूप से इंटरफ़ेस नहीं बना सकताCloneable
(उपयोग के समान Serializable
)। यह बिना प्रतिबिंब के नहीं किया जा सकता है:
ISomething i = ...
if (i instanceof Cloneable) {
//DAMN! I Need to know about ISomethingImpl! Unless...
copy = (ISomething) i.getClass().getMethod("clone").invoke(i);
}
जोश बलोच के प्रभावी जावा से उद्धरण :
"क्लोन करने योग्य इंटरफ़ेस का उद्देश्य वस्तुओं के लिए एक मिश्रित इंटरफ़ेस के रूप में किया गया था ताकि वे क्लोनिंग की अनुमति दे सकें। दुर्भाग्य से यह इस उद्देश्य की पूर्ति करने में विफल रहता है ... यह इंटरफेस का अत्यधिक atypical उपयोग है और अनुकरण करने के लिए नहीं। ... किसी वर्ग पर प्रभाव डालने के लिए इंटरफ़ेस को लागू करने के लिए, उसे और उसके सभी सुपरक्लासेस को एक काफी जटिल, अप्राप्य और बड़े पैमाने पर अनिर्दिष्ट प्रोटोकॉल का पालन करना चाहिए "
Serializable
- यह लागू करने के लिए निर्णय लेने के लिए है Serializable
। मैं इसे बढ़ा रहा था Cloneable
- यह ऐसा कुछ नहीं है जिसे एक इंटरफ़ेस का विस्तार करना चाहिए - लेकिन एक इंटरफ़ेस का कार्यान्वयन मुफ्त है Cloneable
। मुसीबत यह है, यदि आपके पास इंटरफ़ेस प्रकार का पैरामीटर है, तो आप पूछते हैं कि क्या यह क्लोन करने योग्य है; लेकिन फिर आप वास्तव में इसे क्लोन नहीं कर सकते हैं!
क्लोन करने योग्य इंटरफ़ेस सिर्फ एक मार्कर है जो कह रहा है कि वर्ग क्लोन का समर्थन कर सकता है। यह विधि संरक्षित है क्योंकि आपको इसे ऑब्जेक्ट पर कॉल नहीं करना चाहिए, आप इसे सार्वजनिक कर सकते हैं (और चाहिए)।
सूर्य से:
क्लास ऑब्जेक्ट में, क्लोन () विधि संरक्षित घोषित की जाती है। यदि आप सभी क्लोन करने योग्य लागू करते हैं, तो केवल उप-वर्ग और एक ही पैकेज के सदस्य ऑब्जेक्ट पर क्लोन () को लागू करने में सक्षम होंगे। क्लोन () विधि का उपयोग करने के लिए किसी भी पैकेज में किसी भी वर्ग को सक्षम करने के लिए, आपको इसे ओवरराइड करना होगा और इसे सार्वजनिक घोषित करना होगा, जैसा कि नीचे किया गया है। (जब आप किसी विधि को ओवरराइड करते हैं, तो आप इसे कम निजी बना सकते हैं, लेकिन अधिक निजी नहीं। यहां, ऑब्जेक्ट में संरक्षित क्लोन () विधि को सार्वजनिक विधि के रूप में ओवरराइड किया जा रहा है।)
Set
clone
यह संरक्षित है क्योंकि यह कुछ ऐसा है जिसे अतिरंजित होना चाहिए ताकि यह वर्तमान वर्ग के लिए विशिष्ट हो। हालांकि यह एक सार्वजनिक clone
विधि बनाना संभव होगा, जो किसी भी वस्तु को इस सब पर क्लोन कर सकेगा, विशेष रूप से उस वर्ग के लिए लिखी गई विधि के रूप में अच्छा नहीं होगा जिसकी उसे आवश्यकता है।
क्लोन विधि का किसी भी वस्तु पर सीधे उपयोग नहीं किया जा सकता है, यही कारण है कि इसे उपवर्ग द्वारा ओवरराइड करने का इरादा है।
बेशक यह सार्वजनिक हो सकता है और क्लोनिंग संभव नहीं होने पर केवल एक उपयुक्त अपवाद फेंक सकता है, लेकिन मुझे लगता है कि यह भ्रामक होगा।
जिस तरह से क्लोन को अभी लागू किया गया है उससे आपको लगता है कि आप क्लोन का उपयोग क्यों करना चाहते हैं, और आप अपनी वस्तु को क्लोन कैसे करना चाहते हैं।
यह सुरक्षित है क्योंकि डिफ़ॉल्ट कार्यान्वयन सभी क्षेत्रों (निजी सहित) की एक उथली सदस्यवार प्रतिलिपि करता है, जिसमें कंस्ट्रक्शन को दरकिनार किया जाता है । यह ऐसी कोई चीज नहीं है जिसे किसी वस्तु को पहली जगह पर संभालने के लिए डिज़ाइन किया गया हो (उदाहरण के लिए, यह किसी साझा सूची में बनाई गई ऑब्जेक्ट इंस्टेंस का ट्रैक रख सकता है, या कुछ इसी तरह का)।
उसी कारण से, clone()
यदि यह जिस ऑब्जेक्ट पर कॉल किया जाता है , तो डिफ़ॉल्ट कार्यान्वयन लागू नहीं होता है Cloneable
। यह दूरगामी परिणामों के साथ एक संभावित असुरक्षित ऑपरेशन है, और इसलिए कक्षा के लेखक को स्पष्ट रूप से ऑप्ट-इन करना चाहिए।
क्लोन के javadoc से।
* By convention, classes that implement this interface (cloneable) should override
* <tt>Object.clone</tt> (which is protected) with a public method.
* See {@link java.lang.Object#clone()} for details on overriding this
* method.
* Note that this interface does <i>not</i> contain the <tt>clone</tt> method.
* Therefore, it is not possible to clone an object merely by virtue of the
* fact that it implements this interface. Even if the clone method is invoked
* reflectively, there is no guarantee that it will succeed.
इसलिए आप प्रत्येक वस्तु पर क्लोन कह सकते हैं, लेकिन यह आपको अधिकांश समय देगा जो आप चाहते हैं या अपवाद नहीं हैं। लेकिन केवल प्रोत्साहित किया जाता है यदि आप क्लोन करने योग्य लागू करते हैं।
IMHO यह इतना सरल है:
#clone
गैर-क्लोन करने योग्य वस्तुओं पर नहीं बुलाया जाना चाहिए, इसलिए इसे सार्वजनिक नहीं किया जाता है#clone
उपवर्गों द्वारा आह्वान किया जाता है Object
कि सही वर्ग की उथली प्रतिलिपि प्राप्त करने के लिए क्लोन करने योग्य लागू करेंउपवर्गों द्वारा कॉल करने योग्य तरीकों के लिए सही गुंजाइश क्या है, लेकिन अन्य वर्गों द्वारा नहीं?
यह है protected
।
Cloneable
पाठ्यक्रम को लागू करने वाले वर्ग इस पद्धति को सार्वजनिक करेंगे ताकि इसे अन्य वर्गों से बुलाया जा सके।
क्लोन () पद्धति में क्लोन करने योग्य या नहीं के आंतरिक रूप से एक जांच उदाहरण है। यह है कि कैसे जावा टीम ने सोचा था कि क्लोन () विधि के अनुचित उपयोग को प्रतिबंधित करेगा। विधि () विधि संरक्षित है या केवल उपवर्ग द्वारा पहुँचा है। चूंकि ऑब्जेक्ट सभी उप-वर्गों का मूल वर्ग है, इसलिए क्लोन () पद्धति का उपयोग सभी वर्गों द्वारा किया जा सकता है, यदि हमारे पास 'क्लोन योग्य के उदाहरण' की जाँच से ऊपर नहीं है। यही कारण है कि जावा टीम ने क्लोन () विधि में चेक के होने से क्लोन () विधि के अनुचित उपयोग को प्रतिबंधित करने के लिए सोचा होगा।
इसलिए जो भी वर्ग क्लोन करने योग्य हैं वे ऑब्जेक्ट क्लास के क्लोन () पद्धति का उपयोग कर सकते हैं।
इसके अलावा जब से इसे संरक्षित किया गया है, यह केवल उन उप वर्गों के लिए उपलब्ध है जो क्लोन करने योग्य इंटरफ़ेस को लागू करते हैं। यदि हम इसे सार्वजनिक करना चाहते हैं, तो इस विधि को उप-वर्ग द्वारा अपने स्वयं के कार्यान्वयन के साथ ओवरराइड करना होगा।
हां, वही समस्या जो मुझे मिली। लेकिन मैं इस कोड को लागू करके इसे हल करता हूं
public class Side implements Cloneable {
public Side clone() {
Side side = null;
try {
side = (Side) super.clone();
} catch (CloneNotSupportedException e) {
System.err.println(e);
}
return side;
}
}
जैसा पहले किसी ने कहा था।
खैर, यह भी सूर्य डेवलपर्स केवल मानव हैं, और उन्होंने वास्तव में क्लोन पद्धति को संरक्षित करने के लिए लागू करने के लिए बहुत बड़ी गलती की थी, वही गलती उन्होंने ArrayList में गैर-कामकाजी क्लोन विधि को लागू किया! तो, सामान्य तौर पर, क्लोन विधि के बारे में भी अनुभवी जावा प्रोग्रामर की बहुत गहरी गलतफहमी मौजूद है।
हालाँकि, मैंने हाल ही में अपनी सभी सामग्री के साथ किसी भी वस्तु को कॉपी करने के लिए एक तेज़ और आसान समाधान पाया है, चाहे वह कैसे बनाया गया हो और इसमें क्या शामिल है, मेरा जवाब यहां देखें: Object.clone () का उपयोग करने में बग
फिर से, जावा JDK फ्रेमवर्क शानदार सोच दिखाता है:
क्लोन करने योग्य इंटरफ़ेस में "सार्वजनिक टी क्लोन () नहीं है;" विधि क्योंकि यह एक विशेषता की तरह अधिक कार्य करता है (जैसे। Serializable) जो एक उदाहरण को क्लोन करने की अनुमति देता है।
इस डिज़ाइन में कुछ भी गलत नहीं है क्योंकि:
Object.clone () वह नहीं करेगा जो आप अपने कस्टम-परिभाषित वर्ग के साथ चाहते हैं।
यदि आपके पास माइक्लास लागू है क्लोन करने योग्य => आप "सार्वजनिक MyClass क्लोन (") के साथ क्लोन () को अधिलेखित करते हैं।
यदि आपके पास MyInterface का विस्तार करने योग्य है और MyInterface को लागू करने वाले कुछ MyClasses: बस "सार्वजनिक MyInterface क्लोन ();" इंटरफ़ेस में और MyInterface ऑब्जेक्ट्स का उपयोग करने वाली प्रत्येक विधि उन्हें क्लोन करने में सक्षम होगी, कोई फर्क नहीं पड़ता कि उनका MyClass- वर्ग।