कक्षा क्यों सील करें?


96

मैं सुनना चाहता हूँ कि .Net ढांचे में सील वर्गों के थोक के पीछे प्रेरणा क्या है। किसी वर्ग को सील करने से क्या लाभ है? मैं इस बात की थाह नहीं लगा सकता कि वंशानुक्रम की अनुमति देना कैसे उपयोगी हो सकता है और सबसे अधिक संभावना है कि इन वर्गों से लड़ने वाला ही नहीं।

तो, इस तरह से रूपरेखा क्यों बनाई गई है और क्या यह सब कुछ को बदलने के लिए असहनीय परिवर्तन नहीं होगा? एक और कारण होना चाहिए लेकिन सिर्फ बुराई है?



जवाबों:


41
  • कभी-कभी कक्षाएं बहुत कीमती होती हैं और उन्हें विरासत में तैयार नहीं किया जाता है।
  • प्रकारों की तलाश करते समय सील किए गए वर्गों के बारे में रनटाइम / रिफ्लेक्शन उत्तराधिकार धारणा बना सकते हैं। इसका एक बड़ा उदाहरण है - विशेषताओं को लुकअप रनटाइम गति के लिए सील करने की सिफारिश की जाती है। type.GetCustomAttributes (टाइपोफ़ (MyAttribute)) यदि MyAttribute को सील किया गया है, तो यह बहुत तेज़ी से प्रदर्शन करेगा।

इस विषय के लिए MSDN आलेख सीलिंग क्लासेस द्वारा विस्तार क्षमता सीमित है


3
खुशी है कि वे स्पष्ट रूप से कहते हैं "सावधानी के साथ उपयोग करें" ... काश वे अभ्यास करते हैं जो वे हालांकि उपदेश देते हैं।
मिमीिका

13
यह मेरे लिए बुरी सलाह की तरह लग रहा है :(
जॉन स्कीट

4
@CVertex: क्षमा करें, मैं आपकी आलोचना करने की कोशिश नहीं कर रहा था - सिर्फ लेख।
जॉन स्कीट

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

1
@CVertex यदि आपने .NET का उपयोग किया है, तो संभवतः आप समस्या में चले गए हैं और अभी ध्यान नहीं दिया गया है। लगभग सभी .NET कोर कक्षाएं सील कर दी गई हैं।
कोरीजी

105

कक्षाएं या तो वंशानुक्रम के लिए डिज़ाइन की जानी चाहिए या इसे प्रतिबंधित करना चाहिए। विरासत के लिए डिजाइन करने की लागत है:

  • यह आपके कार्यान्वयन को कम कर सकता है (आपको यह घोषित करना होगा कि कौन सी विधियाँ कॉल करने जा रही हैं, अन्य विधियाँ, यदि कोई उपयोगकर्ता एक को नहीं बल्कि दूसरे को ओवरराइड करता है)
  • यह सिर्फ प्रभाव के बजाय आपके कार्यान्वयन को प्रकट करता है
  • इसका मतलब है कि आपको डिजाइन करते समय अधिक संभावनाओं के बारे में सोचना होगा
  • समतुल्य पेड़ की बराबरी करने के लिए समतुल्य चीजें समान हैं
  • इसके लिए अधिक दस्तावेज की आवश्यकता होती है
  • एक अपरिवर्तनीय प्रकार, जिसे उपवर्गित किया गया है, वह परिवर्तनशील हो सकता है (ick)

प्रभावी जावा का आइटम 17 इस पर अधिक विवरण में जाता है - इस तथ्य के बावजूद कि यह जावा के संदर्भ में लिखा गया है, यह सलाह .NET के साथ भी लागू होती है।

व्यक्तिगत रूप से मेरी इच्छा है कि .NET में डिफ़ॉल्ट रूप से कक्षाएं सील की गईं।


26
हम्म .. यदि आप एक वर्ग का विस्तार करते हैं, तो क्या आप इसे तोड़ते हैं तो यह आपकी समस्या नहीं है?
एमिमिका 11

25
क्या होगा यदि एक कार्यान्वयन परिवर्तन जिसका आधार वर्ग पर आपका कोई नियंत्रण नहीं है, आपको तोड़ देता है? किसकी गलती है? वंशानुक्रम नाजुकता का परिचय देता है, मूल रूप से। वंशानुक्रम पर अनुकूल रचना मजबूती, आईएमओ को बढ़ावा देती है।
जॉन स्कीट

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

8
@ जोआन: रचना एक "है-ए" के बजाय "ए-रिलेशनशिप" है। इसलिए यदि आप एक वर्ग लिखना चाहते हैं जो कुछ तरीकों से एक सूची की तरह काम कर सकता है, लेकिन दूसरों में नहीं, तो आप सूची <T> के सदस्य से प्राप्त करने के बजाय, सूची <T> सदस्य चर के साथ एक वर्ग बनाना चाहते हैं। फिर आप विभिन्न तरीकों को लागू करने के लिए सूची का उपयोग करेंगे।
जॉन स्कीट

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

8

ऐसा लगता है कि सीलिंग पर आधिकारिक Microsoft दिशानिर्देश इस प्रश्न के ~ 9 साल पहले पूछे जाने के बाद विकसित हुए हैं, और वे ऑप्ट-इन दर्शन (डिफ़ॉल्ट रूप से सील) से ऑप्ट-आउट करने के लिए चले गए (डिफ़ॉल्ट रूप से सील न करें):

X ऐसा करने का एक अच्छा कारण के बिना कक्षाओं को सील करें।

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

कक्षा को सील करने के अच्छे कारणों में निम्नलिखित शामिल हैं:

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

X मुहरबंद प्रकारों पर संरक्षित या आभासी सदस्यों की घोषणा न करें

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

✓ CONSIDER सील करने वाले सदस्य जिन्हें आप ओवरराइड करते हैं। वर्चुअल सदस्यों (वर्चुअल सदस्यों में चर्चा किए गए) को शुरू करने के परिणामस्वरूप होने वाली समस्याएं ओवरराइड्स पर लागू होती हैं, हालांकि कुछ हद तक कम। एक ओवरराइड सील करने से आपको इन समस्याओं से विरासत में पदानुक्रम की शुरुआत होती है।

वास्तव में, यदि आप ASP.Net कोर कोडबेस को खोजते हैं , तो आप केवल 30 घटनाओं के बारे में पाएंगे sealed class, जिनमें से अधिकांश विशेषताएँ और परीक्षण कक्षाएं हैं।

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


4

मुझे यह वाक्य msdn प्रलेखन में मिला: "सील करने के लिए मुख्य रूप से सील वर्गों का उपयोग किया जाता है। क्योंकि उनका उपयोग आधार वर्ग के रूप में कभी नहीं किया जा सकता है, कुछ रन-टाइम अनुकूलन सीलिंग वर्ग के सदस्यों को थोड़ी तेजी से बुला सकते हैं।"

मुझे नहीं पता कि प्रदर्शन सील वर्गों का एकमात्र लाभ है और व्यक्तिगत रूप से मैं भी किसी अन्य कारणों को जानना चाहूंगा ...


4
यह देखना दिलचस्प होगा कि वे किस तरह के प्रदर्शन के बारे में बात कर रहे हैं ...
mmiika

3

उदाहरण के लिए प्रदर्शन एक महत्वपूर्ण कारक है, जावा में स्ट्रिंग वर्ग अंतिम है (<- सील) और इसका कारण केवल प्रदर्शन है। मुझे लगता है कि एक और महत्वपूर्ण बिंदु विस्तार से वर्णित भंगुर आधार वर्ग की समस्या से बचने के लिए है: http://blogs.msdn.com/ericlippert/archive/2004/01/07/virtual-methods-and-brittle-base-classes। aspx

यदि आप एक ढांचा प्रदान करते हैं तो यह स्थिरता विरासत परियोजनाओं के लिए महत्वपूर्ण है और भंगुर आधार वर्ग की समस्या से बचने के लिए अपने ढांचे को उन्नत करना है


जावा में स्ट्रिंग के अंतिम होने का कारण प्रदर्शन नहीं है, यह सुरक्षा है।
सीजरबी

@ सीजरबी: हां, लेकिन यह भी, स्ट्रिंग एक सामान्य जावा वर्ग नहीं है। यह जावा में एकमात्र (मेरा मानना ​​है) वर्ग है जो ऑपरेटर ओवरलोडिंग का समर्थन करता है (अधिक के लिए, यहां देखें , अनुभाग: "यहां तक ​​कि सी और जावा के पास (हार्डकोड) ऑपरेटर ओवरलोडिंग है"), जो एक सामान्य वर्ग में संभव नहीं है। इस वजह से, Stringवर्ग उप-वर्ग के लिए भी संभव नहीं हो सकता है, भले ही वह अंतिम न हो।
वचर्जिन

1

"भंगुर आधार वर्ग समस्या" को रोकने के लिए सील का उपयोग किया जाता है। मुझे MSDN में एक अच्छा लेख मिला जो बताता है कि।


0

सीलिंग आपको कुछ मामूली प्रदर्शन लाभ का एहसास करने की अनुमति देता है। C ++ के अनुसार, JITs और आलसी निराशा की दुनिया में यह कम सच है, लेकिन .NET के बाद से pessimization उतना अच्छा नहीं है क्योंकि जावा कंपाइलर ज्यादातर अलग-अलग डिज़ाइन दर्शन के कारण होते हैं, यह अभी भी उपयोगी है। यह संकलक को बताता है कि यह प्रत्यक्ष रूप से किसी भी आभासी तरीकों को कॉल कर सकता है बजाय उन्हें अप्रत्यक्ष रूप से वाइबल के माध्यम से कॉल कर सकता है।

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


0

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


0

यह निर्धारित करने के लिए कि किसी वर्ग, विधि, या संपत्ति को सील करना है या नहीं, आपको आम तौर पर निम्नलिखित दो बिंदुओं पर विचार करना चाहिए:

• आपके वर्ग को अनुकूलित करने की क्षमता के माध्यम से प्राप्त होने वाले संभावित लाभ लाभ प्राप्त कर सकते हैं।

• कक्षाएं लेने की क्षमता आपकी कक्षाओं को इस तरह से संशोधित कर सकती है कि वे अब सही तरीके से या अपेक्षित रूप से काम नहीं करेंगे।


0

एक और विचार यह है कि सील किए गए वर्गों को आपकी इकाई परीक्षणों में नहीं लगाया जा सकता है। से माइक्रोसॉफ्ट के प्रलेखन :

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.