2009-02-16 17 views
12

नेट फ्रेमवर्क में बड़ी संख्या में कक्षाओं को 'मुहरबंद' के रूप में चिह्नित किया गया है, जो आपको उन वर्गों को विरासत में रखने से रोकते हैं। निश्चित रूप से यह ऑब्जेक्ट ओरिएंटेशन की प्रकृति के खिलाफ जाता है, जहां आप मौजूदा वस्तुओं के व्यवहार को बढ़ा सकते हैं और फिर से परिभाषित कर सकते हैं।नेट में 'मुहरबंद' कीवर्ड क्यों मौजूद है?

क्या 'मुहरबंद' कीवर्ड के अस्तित्व के लिए कोई अच्छा कारण है? सिल्वरलाइट में

उदाहरण के लिए, NotifyCollectionChangedEventArgs बंद है। मैं करना चाहता था ObservableCollection कि AddRange और RemoveRange समर्थित के अपने खुद के संस्करण बनाने, लेकिन NCCEA की सिल्वरलाइट संस्करण नहीं है एक निर्माता कि NewItems के लिए से अधिक आइटम और OldItems गुण है, जो पहले से ही के रूप में परिभाषित कर रहे हैं का समर्थन करता है प्रदान करते हैं ILists। आमतौर पर, मैं बस कक्षा को अपने स्वयं के संस्करण के साथ विस्तारित करता हूं जो न्यूइटम और ओल्डइटम गुणों को ओवरराइड करता है, लेकिन इस मामले में मैं नहीं देख सकता और मुझे कोई कारण नहीं दिख रहा है कि ऐसा क्यों होना चाहिए।

+5

आप एरिक लिपर्ट के ब्लॉग पोस्ट को पढ़ना चाहेंगे क्यों .NET ढांचे में अधिकांश चीजें सील कर दी गई हैं: http://blogs.msdn.com/ericlippert/archive/2004/01/22/61803.aspx – gix

+0

क्योंकि जावा 'अंतिम' श्रेणी संशोधक/एस –

उत्तर

21

डिजाइनिंग वर्गों (या चौखटे) एक्स्टेंसिबल होने के लिए तुच्छ नहीं है, और डाल बस विरासत ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग के एक सिद्धांत नहीं है।

तो sealed डेवलपर/डिजाइनर व्यक्त करने और उन इरादों को बचाने के लिये अनुमति देने के लिए मौजूद है। एक वर्ग को सील करना रखरखाव बोझ को कम करके अपने जीवन को आसान बना सकता है। यह मूल डेवलपर को यह नियंत्रित करने की अनुमति देता है कि वर्ग (या ढांचा) कैसे बढ़ाया जाता है, ताकि वे अन्य कोड में परिवर्तन तोड़ने के बारे में चिंता किए बिना आंतरिक परिवर्तन कर सकें।

एक सिद्धांत यह है कि डेवलपर्स को डिफ़ॉल्ट रूप से पत्ता कक्षाओं को सील करना चाहिए। फिर, जब डेवलपर जानबूझकर एक असीमित वर्ग बनाता है, तो यह उन्हें विस्तारशीलता के बारे में सोचने के लिए मजबूर करता है।


रेफरी: एरिक Lippert - Why Are So Many Of The Framework Classes Sealed?

+0

मुझे लगता है कि मैं यहां कुछ गलत पढ़ रहा हूं। मैंने आपको पढ़ा है कि यह ढांचे के लिए डेवलपर्स के इरादे को संरक्षित करने के लिए बनाया गया है ** और ** हमें स्थानीय विकास को आसान बनाने के लिए डिफ़ॉल्ट रूप से किसी भी वर्ग को सील करना चाहिए। ऐसा लगता है कि यह पहला विचार है, क्योंकि यदि आप सभी कक्षाओं को सील करते हैं तो आप जो भी अपनी ढांचे का उपयोग करेंगे, उन्हें बहुत परेशानी होगी। अन्यथा, अगर हमें लगता है कि हमें एक मुहरबंद कक्षा का विस्तार करने की आवश्यकता है तो हमें क्या करना चाहिए? तो, शायद यह मदद करता है अगर आप एक अच्छा व्यावहारिक उदाहरण दे सकते हैं कि इसका उपयोग कब और कब किया जाना चाहिए और यह क्यों अच्छा है कि यह मौजूद है। क्या आप? :-) – cregox

+0

@ कावासा मैं वास्तव में केवल विरासत विस्तार बिंदु प्रदान करने की वकालत कर रहा हूं जब इसे डिज़ाइन और सोचा गया हो। आदर्श रूप से एक सरल कोडबेस दीर्घकालिक रखरखाव लागत को कम करके आपके जीवन को आसान बना देगा। –

+0

ठीक है, फिर वापस मैं किसी भी पृष्ठभूमि के बिना समझने की कोशिश कर रहा था, सवाल पर एक ही बात पूछी गई। * क्यों 'मुहरबंद' भी मौजूद है *। और आपके जवाब ने मेरे लिए यह नहीं किया। अब मैं देख सकता हूं कि आप कहां से आ रहे हैं। और जो कुछ मैंने याद किया वह सभी विवरण में है ... मुझे एक संपादन का प्रस्ताव देने की अनुमति दें। ;-) – cregox

2

संक्षिप्त उत्तर है, क्योंकि माइक्रोसॉफ्ट ऐसा कहा। लंबा जवाब यह है कि माइक्रोसॉफ्ट ने विस्तारित विधियों नामक मुहरबंद वर्गों का विस्तार करने के लिए एक तंत्र प्रदान किया है।

सामान्यतः, कक्षाओं को विस्तारित करना एक बुरा विचार है, जिनके पास आपके पास स्रोत कोड नहीं है। उदाहरण के लिए, आप नहीं जानते कि ऑब्जेक्ट के आंतरिक डेटा में कॉलिंग बेस विधि क्या करती है। हां, आप परावर्तक या जो भी इसे समझने के लिए उपयोग कर सकते हैं, लेकिन आम तौर पर रचना या विस्तार विधियों का उपयोग करना बेहतर होता है।

आपको यह भी विचार करना होगा कि वास्तव में क्या विरासत है। यह वर्ग को बदलने का सिर्फ एक तरीका नहीं है, यह बहुरूपता भी प्रदान करता है। क्या होगा यदि आप स्ट्रिंग क्लास के अर्थशास्त्र को बदलते हैं, तो आप अपनी नई स्ट्रिंग क्लास को उस ऑब्जेक्ट में पास करते हैं जो स्ट्रिंग को किसी विशिष्ट तरीके से कार्य करने की अपेक्षा करता है? मोहरबंद अनिवार्य रूप से अनुबंध को लागू करता है कि यह वस्तु हमेशा जिस तरह से आप उम्मीद करते हैं उस पर काम करेगी।

+0

है लेकिन यदि मेरे पास एक नई सुपरस्ट्रिंग क्लास है जो स्ट्रिंग को बढ़ाती है, और यह अन्य वर्गों की अपेक्षा करने का तरीका नहीं है, तो निश्चित रूप से यह सुपरस्टिंग क्लास के कार्यान्वयनकर्ता के रूप में मेरी समस्या है। ऐसा लगता है कि एक वर्ग को सील करने के लिए मूर्खतापूर्ण लगता है क्योंकि एक और डेवलपर * इसे तोड़ सकता है। –

+0

यह ठीक होगा अगर आप केवल अपने कोड में एक स्ट्रिंग का उपयोग कर रहे थे। लेकिन स्ट्रिंग जैसी कक्षाएं पूरे ढांचे में उपयोग की जाती हैं। माइक्रोसॉफ्ट यह सुनिश्चित करना चाहता है कि वे अपने उपयोग के लिए नहीं बदलते हैं। –

1

जबकि मैं सहमत हूं कि .NET शायद बहुत अधिक सील करता है, यह आमतौर पर पारिस्थितिकी तंत्र की अखंडता की रक्षा करता है। जब आपकी शीर्ष प्राथमिकताओं में से एक है अपने समग्र ढांचे/एपीआई/रनटाइम स्थिर रखना, और वर्गों के बीच कुछ हद तक नाजुक परस्पर निर्भरताएं हैं, तो लोगों को उस व्यवहार को ओवरराइड करने और अनजाने में मूल कार्यक्षमता को अस्थिर करने से रोकने के लिए सबसे सुरक्षित हो सकता है।

फिर भी, मुझे लगता है कि .NET टीम बहुत से वर्गों को सील करती है। कभी-कभी डेवलपर के हिस्से पर सीलिंग सरल आलस्य हो सकती है क्योंकि एक उचित वर्ग डिजाइन बहुत अधिक काम करेगा।

6

कुछ हद तक एक संबंधित सवाल मैं आज से पूछा एक वर्ग सील के प्रयोजनों के स्पष्ट मदद कर सकता है से इस उत्तर:

मैं अपने आप को पूछ है कि एक ही सवाल जब तक मैं अपने ही की पुन: प्रयोज्य पुस्तकालयों पर काम शुरू कर पाया। कई बार आप कुछ कक्षाओं के साथ हवाओं को घुमाते हैं जिन्हें केवल के बिना विस्तारित नहीं किया जा सकता है, जो कार्यान्वयनकर्ता से कॉल के अस्पष्ट या आर्केन अनुक्रम की आवश्यकता होती है।

जब अपने वर्ग जा बढ़ाया करने की इजाजत दी, आप से पूछना करने के लिए है: अगर एक डेवलपर मेरी कक्षा फैली हुई है, और इस नई श्रेणी को मेरी लाइब्रेरी में गुजरता है, मैं पारदर्शी रूप से इस नए वर्ग के साथ काम कर सकते हैं? क्या मैं इस नई कक्षा के साथ ठीक से काम कर सकता हूं? इस नई श्रेणी वास्तव में ही व्यवहार करने के लिए जा रहा है?

मैं पाया है कि नेट फ्रेमवर्क में सील वर्गों अंडर-हुड कुछ आवश्यकताओं कि आप में से, जानकारी नहीं है और है कि मौजूदा कार्यान्वयन दिया नहीं किया जा सकता है समय के सबसे सुरक्षित रूप से उपclasses के संपर्क में।

Liskov Substition and Composition

अब जब कि लिंक का पालन करें और वास्तविक लेखक वोट दें।

2

बहुत गहराई से खोदने के बिना, समझें कि माइक्रोसॉफ्ट एक वर्ग को सील करने का पक्ष लेता है जब संभावित सुरक्षा, रखरखाव या पिछड़ा-संगतता समस्याएं होती हैं जिन्हें इसे डाउनस्ट्रीम से निपटना होगा। उदाहरण के लिए, System.String सुरक्षा और प्रदर्शन के कारणों के लिए बंद है।

इस विशेष मामले में, आपको एक माइक्रोसॉफ्ट डेवलपर से पूछना होगा कि उन्होंने उस वर्ग को सील करने का फैसला क्यों किया। हालांकि, वास्तु मार्गदर्शन साहित्य मैं हाल ही में पढ़ने किया गया है के लिए एक दृष्टिकोण के पक्ष में जाता है "मुहर जब तक आप इसे बढ़ाया जा करने की आवश्यकता होगी पता ।" यह साहित्य जहां संभव हो एक्सटेंशन एक्सटेंशन का उपयोग करके espouse करने के लिए जाता है। (मैं यह नहीं कह रहा हूँ मैं इसके साथ सहमत हैं, मैं सिर्फ कह रहा है कि मैं क्या हाल ही में पढ़ने आ रहे हैं।)

यहां तक ​​कि अगर वर्ग सील नहीं किया गया, सवाल में गुण हो सकता है नहीं आभासी छोड़ दिया गया है, जो आपको अभी भी क्रीक छोड़ देगा।

अपने विशिष्ट परिदृश्य में, मैं अपना अनूठा नाम के साथ विस्तार के तरीकों के साथ जाना चाहते हैं। यह सब कुछ आप कर सकते हैं।

0

यह निर्भर करता है, वहाँ सिर्फ instantiated करने का इरादा कर रहे हैं कि वर्गों (विरासत, अगर मौजूद है, बस कार्यान्वयन को आसान बनाने के लिए किया जाता है) कर रहे हैं, अन्य वर्गों के लिए लक्षित हैं एक spesific कार्यान्वयन प्रदान करने के लिए विरासत में हो।

मुहरबंद कक्षाएं कुछ फायदे हैं:

  • वे किसी भी आभासी तरीकों की जरूरत नहीं है, इसलिए वे गैर- "अपवाद सुरक्षित" लागू किया अधिभावी तरीकों के बारे में चिंता करने की जरूरत नहीं है।
  • यदि कोई वर्ग अपरिवर्तनीय है तो यह अपरिवर्तनीयता को संरक्षित और गारंटी दे सकता है।

अन्यथा यदि आप "आराम" तरीकों के साथ एक मोहरबंद वर्ग को सजाने के लिए चाहते हैं विस्तार तरीकों (सी # 3.0) का उपयोग करें।

0

केवल किसी चीज़ को एक वस्तु है, इसका मतलब यह नहीं है कि यह हमेशा खुली सब लोग बढ़ाने या यह व्यवहार है फिर से परिभाषित करने के लिए किया जाना चाहिए।

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

बेशक

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

1

मेरा सुझाव है वहाँ अन्य अज्ञानी -err की रक्षा के लिए की तुलना में कक्षाएं सील के लिए कोई अच्छा कारण है कि, मैं निर्दोष मतलब है। आप पुरानी कहावत जानते हैं, "उन्हें पर्याप्त रस्सी दी गई और वे खुद को लटकाएंगे"। उन्हें बोलने दो। शायद यह मेरी सी ++ पृष्ठभूमि है, लेकिन मुझे यह जानकर काफी सहजता है कि अगर मैं मेहनती नहीं हूं तो मेरे पास चीजों को पूरी तरह से भरने की शक्ति है।

मैं इंटरफ़ेस द्वारा कार्यक्रम के लिए करते हैं। इंटरफेस निश्चित रूप से सार्वजनिक हैं और कोई भी अपना स्वयं का कार्यान्वयन प्रदान करने के लिए स्वतंत्र है जो इंटरफ़ेस द्वारा व्यक्त अनुबंध का पालन करता है। इन इंटरफेस को लागू करने वाले मेरे ठोस वर्ग एक निजी चिंता के रूप में होते हैं और इन्हें आंतरिक और/या निजी चिह्नित किया जाता है। मुझे नहीं लगता कि मुझे ऐसी कक्षाओं को सील करने की जरूरत है।

कहाँ कोड पुन: उपयोग के लिए वांछनीय है, मैं विरासत के माध्यम से पुन: उपयोग से बचने, संरचना और अन्य तकनीकों के पक्ष में।

सीलिंग उन प्रकारों पर मान्य भी हो सकती है जिन्हें सादे-पुराने डेटा प्रकार माना जाता है, लेकिन मुझे इस पर कोई रास्ता नहीं है।

0

व्यावहारिक उपयोगों में से एक जहां मैंने सील किए गए कीवर्ड को उपयोगी पाया है, वह "बेकार वर्ग के मुद्दों" से बचने के लिए है। यहां एक वीडियो है जो नाजुक बेस क्लास मुद्दों में से एक को दिखाता है http://www.youtube.com/watch?v=xnA3RUJcyY4

मुझे थोड़ा विस्तार से समझाएं।

नीचे दिए गए परिदृश्य पर विचार करें जहां हमारे पास एक वर्चुअल विधि "सम्मिलित" के साथ "डीबीपेरेंट" नामक अभिभावक वर्ग है।

वर्ग DbParent {

public virtual void Insert() 
    { 
     Console.WriteLine("Parent insert"); 
    } 

}

नीचे अपने ही "डालें" कार्यान्वयन जो विभिन्न स्थानों पर स्थापित किया गया है के साथ एक सरल बच्चे वर्ग है।

class DbChildClass : DbParent 
    { 
    public void Insert() 
    { 
     Console.WriteLine("Child inserts"); 
    } 

}

अब तैनाती माता पिता वर्ग डेवलपर्स के कुछ महीनों के बाद मान लीजिए प्रभाव को समझने के बच्चे कक्षाओं जाने के लिए और एक नई पद्धति "जोड़ें" जोड़ने पर बिना। यह "जोड़ें" विधि आंतरिक रूप से "सम्मिलित करें" विधि को कॉल करती है (नीचे कोड स्निपेट नीचे है)।

class DbParent 
    { 
    public void Add() // Adds method with out consulting 
    { 
    this.Insert(); 
    } 

    public virtual void Insert() 
    { 
     Console.WriteLine("Parent insert"); 
    } 
    } 

अब क्लाइंट प्रोग्राम जो बच्चे वर्ग ऑब्जेक्ट बनाने के द्वारा "जोड़ें" विधि आह्वान उम्मीद करते हैं कि "बाल" वर्ग "डालें" कार्यान्वयन बुलाया जाना चाहिए।

DbChildClass o = new DbChildClass(); 
    o.Add(); 
    Console.Read(); 

लेकिन whoaaaa, तो आप नीचे दिए गए कोड आप माता-पिता वर्ग "डालें" कहा जाता है की उम्मीद नहीं है देखेंगे चलाते हैं।

तो मैं इस तरह के मुद्दों से बचने के लिए कक्षा को "मुहरबंद" के रूप में चिह्नित और चिह्नित करूंगा।

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