जावा में वंशानुक्रम को प्रतिबंधित करने के लिए अच्छे कारण क्या हैं, उदाहरण के लिए एक एकल, निजी पैरामीटर रहित कंस्ट्रक्टर का उपयोग करके अंतिम वर्गों या कक्षाओं का उपयोग करना? विधि को अंतिम बनाने के अच्छे कारण क्या हैं?
जावा में वंशानुक्रम को प्रतिबंधित करने के लिए अच्छे कारण क्या हैं, उदाहरण के लिए एक एकल, निजी पैरामीटर रहित कंस्ट्रक्टर का उपयोग करके अंतिम वर्गों या कक्षाओं का उपयोग करना? विधि को अंतिम बनाने के अच्छे कारण क्या हैं?
जवाबों:
यहां आपका सबसे अच्छा संदर्भ यहोशू बलोच की उत्कृष्ट पुस्तक "प्रभावी जावा" का आइटम 19 है, जिसे "डिजाइन और दस्तावेज़ विरासत के लिए कहा जाता है या इसे निषिद्ध करें"। (यह दूसरे संस्करण में आइटम 17 है और पहले संस्करण में आइटम 15 है।) आपको वास्तव में इसे पढ़ना चाहिए, लेकिन मैं संक्षेप में बताऊंगा।
अपने माता-पिता के साथ विरासत में मिली कक्षाओं की बातचीत अगर पूर्वज से विरासत में लेने के लिए डिज़ाइन नहीं की गई तो आश्चर्य और अप्रत्याशित हो सकती है।
इसलिए कक्षाएं दो प्रकारों में आनी चाहिए:
विस्तारित किए जाने के लिए डिज़ाइन की गई कक्षाएं , और यह कैसे किया जाना चाहिए, इसका वर्णन करने के लिए पर्याप्त प्रलेखन के साथ
कक्षाएं अंतिम रूप से चिह्नित हैं
यदि आप विशुद्ध रूप से आंतरिक कोड लिख रहे हैं तो यह थोड़ा अधिक हो सकता है। हालाँकि एक कक्षा फ़ाइल में पाँच वर्ण जोड़ने का अतिरिक्त प्रयास बहुत कम है। यदि आप केवल आंतरिक comsumption के लिए लिख रहे हैं तो एक भविष्य कोडर हमेशा 'अंतिम' निकाल सकता है - आप इसे एक चेतावनी के रूप में सोच सकते हैं "यह वर्ग मन में विरासत के साथ नहीं बनाया गया था"।
आप एक विधि को अंतिम रूप देना चाहते हैं ताकि ओवरराइडिंग क्लासेस व्यवहार को बदल न सकें जो अन्य विधियों में गिना जाता है। कंस्ट्रक्टरों में कहे जाने वाले तरीके अक्सर फाइनल घोषित कर दिए जाते हैं ताकि आपको ऑब्जेक्ट बनाते समय कोई अप्रिय आश्चर्य न हो।
final
।
3 उपयोग मामले हैं जहां आप अंतिम तरीकों के लिए जा सकते हैं।
कक्षा को अंतिम बनाने का उद्देश्य:
ताकि कोई भी निकाय उन वर्गों का विस्तार न कर सके और अपना व्यवहार बदल सके।
जैसे: रैपर क्लास इंटेगर एक अंतिम वर्ग है। यदि वह वर्ग अंतिम नहीं है, तो कोई भी इंटेगर को अपनी कक्षा में विस्तारित कर सकता है और पूर्णांक वर्ग के मूल व्यवहार को बदल सकता है। इससे बचने के लिए, जावा ने सभी रैपर वर्गों को अंतिम कक्षाओं के रूप में बनाया।
DerivedInteger
, यह अभी भी मूल इंटेगर वर्ग को नहीं बदलता है, और जो कोई भी DerivedInteger
अपने जोखिम पर ऐसा करता है, इसलिए मुझे अभी भी नहीं मिलता है कि यह एक समस्या क्यों है।
आप अपरिवर्तनीय वस्तुएं बनाना चाहते हैं ( http://en.wikipedia.org/wiki/Immutable_object ), आप एक सिंगलटन ( http://en.wikipedia.org/wiki/Singleton_pattern ) बनाना चाहते हैं , या आप चाहते हो सकते हैं किसी को दक्षता, सुरक्षा या सुरक्षा के कारणों के लिए विधि को ओवरराइड करने से रोकने के लिए।
विरासत एक जंजीर की तरह है - बहुत शक्तिशाली, लेकिन गलत हाथों में भयानक। या तो आप उनसे विरासत में प्राप्त की जाने वाली कक्षा डिजाइन करें (जो लचीलेपन को सीमित कर सकती है और अधिक समय ले सकती है) या आपको इसे प्रतिबंधित करना चाहिए।
प्रभावी जावा 2 संस्करण आइटम 16 और 17, या मेरा ब्लॉग पोस्ट "इनहेरिटेंस टैक्स" देखें ।
हम्म् ... मैं दो बातें सोच सकता हूं:
आपके पास एक वर्ग हो सकता है जो कुछ सुरक्षा मुद्दों से निपटता है। इसे उप-वर्ग करके और आपके सिस्टम को इसके उप-संस्करण को खिलाकर, एक हमलावर सुरक्षा प्रतिबंधों को दरकिनार कर सकता है। उदाहरण के लिए, आपका एप्लिकेशन प्लग इन का समर्थन कर सकता है और यदि कोई प्लग इन आपकी सुरक्षा संबंधित कक्षाओं को उपवर्गित कर सकता है, तो वह इस ट्रिक का उपयोग किसी भी तरह से उप-वर्ग किए गए संस्करण को स्मगल करने के लिए कर सकता है। हालाँकि, यह कुछ ऐसा है जो सूर्य को एप्लेट और इस तरह से संबंधित है, शायद ऐसा कोई यथार्थवादी मामला नहीं है।
एक वस्तु से बचने के लिए एक और अधिक यथार्थवादी एक पारस्परिक परिवर्तन हो जाता है। जैसे कि स्ट्रिंग्स अपरिवर्तनीय हैं, आपका कोड सुरक्षित रूप से इसके संदर्भ रख सकता है
String blah = someOtherString;
पहले स्ट्रिंग को कॉपी करने के बजाय। हालाँकि, यदि आप स्ट्रिंग को उप-वर्ग कर सकते हैं, तो आप इसमें ऐसे तरीके जोड़ सकते हैं जो स्ट्रिंग मान को संशोधित करने की अनुमति देते हैं, अब कोई भी कोड इस बात पर भरोसा नहीं कर सकता है कि स्ट्रिंग वही रहेगी यदि यह उपरोक्त स्ट्रिंग को कॉपी करता है, इसके बजाय इसे डुप्लिकेट करना होगा स्ट्रिंग।
इसके अलावा, यदि आप एक वाणिज्यिक बंद स्रोत वर्ग लिख रहे हैं, तो हो सकता है कि आप लोगों को लाइन के नीचे की कार्यक्षमता को बदलने में सक्षम न हों, खासकर यदि यू को इसके लिए समर्थन देने की आवश्यकता हो और लोगों ने आपके तरीके को ओवरराइड कर दिया हो और शिकायत कर रहे हों कि यह कॉलिंग देता है अप्रत्याशित परिणाम।
यदि आप वर्गों और विधियों को अंतिम रूप से चिह्नित करते हैं, तो आप एक छोटे प्रदर्शन लाभ को देख सकते हैं, क्योंकि रनटाइम को किसी दिए गए ऑब्जेक्ट के लिए आमंत्रित करने के लिए सही वर्ग विधि नहीं दिखती है। गैर-अंतिम तरीकों को आभासी के रूप में चिह्नित किया जाता है ताकि जरूरत पड़ने पर उन्हें ठीक से बढ़ाया जा सके, अंतिम तरीकों को कक्षा में सीधे लिंक या संकलित इनलाइन किया जा सके।
लोगों को ऐसे काम करने से रोकना जो खुद को और दूसरों को भ्रमित कर सकें। एक भौतिकी पुस्तकालय की कल्पना करें जहां आपके पास कुछ परिभाषित स्थिरांक या गणनाएं हैं। अंतिम कीवर्ड का उपयोग किए बिना, कोई भी साथ आ सकता है और बुनियादी गणना या स्थिरांक को फिर से परिभाषित कर सकता है जिसे कभी भी बदलना नहीं चाहिए।
आप एक विधि को अंतिम रूप देना चाहते हैं ताकि ओवरराइडिंग कक्षाएं अपना व्यवहार न बदलें। जब आप व्यवहार को बदलने में सक्षम होना चाहते हैं तो विधि को सार्वजनिक करें। जब आप किसी सार्वजनिक विधि को ओवरराइड करते हैं तो इसे बदला जा सकता है।