2008-09-28 18 views
19

यह this article कि में कहते हैं:अपरिवर्तनीय कक्षा अंतिम होना चाहिए?

क्योंकि यह अपरिवर्तनीय है एक वर्ग अंतिम बनाना ऐसा करने के लिए एक अच्छा कारण है।

मैं थोड़ा इस से हैरान हूँ ... मैं समझता हूँ कि अचल स्थिति धागे की सुरक्षा और सादगी के पीओवी से एक अच्छी बात है, लेकिन ऐसा लगता है कि इन चिंताओं को कुछ हद तक तानाना के लिए ओर्थोगोनल हैं। तो, कक्षा को अंतिम बनाने के लिए अपरिवर्तनीयता का एक अच्छा कारण क्यों है?

उत्तर

9

क्योंकि यदि कक्षा अंतिम है तो आप इसे विस्तारित नहीं कर सकते हैं और इसे व्यवहार्य बना सकते हैं।

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

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

+3

लेकिन आप अतिरिक्त अपरिवर्तनीय गुण जोड़ने के लिए एक अपरिवर्तनीय कक्षा का विस्तार करना चाह सकते हैं। –

+2

"क्योंकि यदि कक्षा अंतिम है तो आप इसे विस्तारित नहीं कर सकते हैं और इसे व्यवहार्य बना सकते हैं" लेकिन आप एक गैर-अंतिम अपरिवर्तनीय वर्ग का विस्तार नहीं कर सकते हैं और इसे व्यवहार्य बना सकते हैं, आप केवल उपclass mutable –

+4

कॉलर के रूप में कर सकते हैं, आप नहीं जानते कि आप अपरिवर्तनीय वर्ग या इसके उत्परिवर्तनीय उप-वर्ग का उपयोग कर रहे हैं - जब तक कि आप सीधे निर्माता को कॉल न करें। वह बहुरूपता है। – slim

10

विस्तार कर सकते हैं लेकिन इसके जनक के अनुबंध को फिर से परिभाषित कभी नहीं Liskov प्रतिस्थापन सिद्धांत एक उपवर्ग के बाद। यदि बेस क्लास अपरिवर्तनीय है तो इसके उदाहरणों को ढूंढना मुश्किल है जहां इसकी कार्यक्षमता को अनुबंध को तोड़ने के बिना उपयोगी रूप से विस्तारित किया जा सकता है।

ध्यान दें कि यह सिद्धांत रूप में संभव है अपरिवर्तनीय वर्ग का विस्तार और आधार क्षेत्रों जैसे बदलने के लिए यदि बेस क्लास में किसी सरणी का संदर्भ होता है तो सरणी के तत्वों को अंतिम घोषित नहीं किया जा सकता है। स्पष्ट रूप से विधियों के अर्थशास्त्र को ओवरराइडिंग के माध्यम से बदला जा सकता है।

मुझे लगता है कि आप सभी क्षेत्रों को निजी और सभी विधियों को अंतिम रूप में घोषित कर सकते हैं, लेकिन फिर विरासत का उपयोग क्या होगा?

+0

कहें कि आपके पास एक अपरिवर्तनीय आकार वर्ग है, जिसमें क्षेत्र की संपत्ति है। आप सर्किल सबक्लास बनाना चाहते हैं जिसमें त्रिज्या जैसे अतिरिक्त गुण हैं। ये नई गुण खुद को अपरिवर्तनीय हो सकती हैं, इस प्रकार माता-पिता की अपरिवर्तनीय संपत्ति को संरक्षित किया जा सकता है। इसमें गलत क्या है? –

+1

मुझे नहीं लगता कि इसमें कुछ भी गलत है, जब तक आप आकार से विस्तार करने वाले एकमात्र व्यक्ति हैं। लेकिन आपको अन्य डेवलपर्स के लिए सटीक दिशानिर्देश बनाना होगा और आश्वस्त रहना होगा कि वे उनका अनुसरण करेंगे। तो मुझे लगता है कि तर्क यह है कि 99।समय अपने प्रयास नहीं लायक ... –

+0

जीजी पैसे पर के के 9%। यदि आप गारंटी देते हैं तो आपको इसे रखना होगा। – CurtainDog

6

मुख्य रूप से सुरक्षा मुझे लगता है। इसी कारण से स्ट्रिंग अंतिम है, कोई भी सुरक्षा-संबंधित कोड अपरिवर्तनीय के रूप में व्यवहार करना चाहता है, वह अंतिम होना चाहिए।

मान लीजिए आप एक वर्ग, अपरिवर्तनीय होने के लिए यह MyUrlClass फोन परिभाषित किया गया है, लेकिन आप इसे अंतिम निशान नहीं है।

अब, किसी को इस तरह से सुरक्षा प्रबंधक कोड लिखने के लिए परीक्षा हो सकती है;

securitymanager.checkUrl(urltoconnect); 
Socket sckt = opensocket(urltoconnect); 
sendrequest(sckt); 
getresponse(sckt); 

लेकिन वे ऐसा नहीं कर सकते, क्योंकि आप MyUrlClass अंतिम नहीं था:

void checkUrl(MyUrlClass testurl) throws SecurityException { 
    if (illegalDomains.contains(testurl.getDomain())) throw new SecurityException(); 
} 

और यहाँ क्या वे अपने DoRequest (MyUrlClass यूआरएल) में डाल दिया था विधि है। कारण यह नहीं है कि वे ऐसा नहीं कर सकते हैं कि अगर उन्होंने किया, तो कोड getDomain() को पहली बार "www.google.com" वापस करने के लिए ओवरराइड करके सुरक्षा प्रबंधक प्रतिबंधों से बच सकता है, और "www.evilhackers.org" दूसरा, और DoRequest() में अपनी कक्षा का एक ऑब्जेक्ट पास कर रहा है।

मैं, वैसे, अगर यह भी मौजूद है evilhackers.org के खिलाफ कुछ भी नहीं है ...

सुरक्षा चिंताओं के अभाव में यह सब के बारे में प्रोग्रामिंग त्रुटियों से परहेज है, और यह आप कैसे आप पर निर्भर निश्चित रूप से है वो करें। उप-वर्गों को अपने माता-पिता के अनुबंध को रखना होता है, और अपरिवर्तनीयता केवल अनुबंध का हिस्सा है। लेकिन यदि किसी वर्ग के उदाहरण अपरिवर्तनीय होने के लिए माना जाता है, तो इसे अंतिम रूप देने के लिए यह सुनिश्चित करने का एक अच्छा तरीका है कि वे वास्तव में सभी अपरिवर्तनीय हैं (यानी कि आसपास के लात मारने वाले उप-वर्गों के उत्परिवर्तनीय उदाहरण नहीं हैं, जिनका उपयोग माता-पिता के कहीं भी किया जा सकता है वर्ग के लिए बुलाया जाता है)।

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

+0

'अंतिम' विधियों को चिह्नित करने के लिए पर्याप्त नहीं होगा? – Pacerier

+0

जैसा कि मैंने कहा, "यह काफी तर्क दिया जा सकता है कि अपने परिसर कक्षाओं में भाग के लिए खाते में करने में नाकाम रहने के लिए कुछ से बचने के लिए है ... लेकिन अगर आप इसे के लिए खाते में नहीं कर सकते, आप कम से कम यह रोकने के द्वारा इस तथ्य का संकेत मिलता है।" । और आप इसे बहस कर रहे हैं। काफी। –

0

प्रदर्शन कारणों से कक्षा को अपरिवर्तनीय बनाने का एक अच्छा विचार भी है। उदाहरण के लिए Integer.valueOf ले लो। जब आप इस स्थैतिक विधि को कॉल करते हैं तो उसे एक नया इंटीजर इंस्टेंस वापस नहीं करना पड़ता है। यह ज्ञान में पहले बनाए गए उदाहरण को सुरक्षित कर सकता है कि जब आपने इसे उस उदाहरण का संदर्भ दिया था, पिछली बार आपने इसे संशोधित नहीं किया था (मुझे लगता है कि यह सुरक्षा कारण परिप्रेक्ष्य से भी अच्छा तर्क है)।

मैं इन मामलों पर प्रभावी जावा में किए गए दृष्टिकोण से सहमत हूं- आपको या तो अपनी कक्षाओं को विस्तार के लिए डिज़ाइन करना चाहिए या उन्हें गैर-एक्स्टेंसिबल बनाना चाहिए। यदि यह कुछ विस्तार करने का आपका इरादा शायद एक इंटरफेस या अमूर्त वर्ग पर विचार करें।

इसके अलावा, आपको कक्षा को अंतिम बनाने की आवश्यकता नहीं है। आप रचनाकारों को निजी बना सकते हैं।

+0

बस कुछ ही नोट्स। 1) आम तौर पर, एक उत्परिवर्तनीय वर्ग उदाहरण एक समकक्ष अपरिवर्तनीय उदाहरण की तुलना में प्रदर्शन कारणों के लिए बेहतर है। अपरिवर्तनीय उदाहरणों आमतौर पर धागे की सुरक्षित है, लेकिन अचल स्थिति लागत तुम भी थोड़ा अलग राज्य के साथ एक नए वस्तु (एक प्रोटोटाइप या एक बिल्डर पद्धति का उपयोग कर) प्राप्त करना चाहते हैं, तो कर रहे हैं। 2) 'Integer.valueOf' एक Flightweight पैटर्न उदाहरण का एक उदाहरण है, और पैटर्न आम तौर पर अचल स्थिति के मामले से संबंधित नहीं है। 3) एक निजी कन्स्ट्रक्टर होने से एक आंतरिक वर्ग का उपयोग कर उप-वर्गीकरण को रोक नहीं सकता है। –

10

इस के लिए विवरण पुस्तक में दी गई है 'प्रभावी जावा'

पर विचार करें जावा में BigDecimal और BigInteger कक्षाएं।

यह व्यापक रूप से समझा नहीं गया था कि अपरिवर्तनीय वर्गों को प्रभावी ढंग से अंतिम जब BigInteger और BigDecimal लिखे गए थे, इसलिए उनके तरीकों के सभी ओवरराइड किया जा सकता होना ही था। दुर्भाग्यवश, पिछड़े संगतता को संरक्षित करते समय इस तथ्य के बाद इसे ठीक नहीं किया जा सका।

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

public static BigInteger safeInstance(BigInteger val) { 

    if (val.getClass() != BigInteger.class) 

    return new BigInteger(val.toByteArray()); 


     return val; 

    } 

आप उप classing अनुमति देते हैं, तो यह अपरिवर्तनीय वस्तु की "पवित्रता" तोड़ सकता।

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