क्या आपको कभी संरक्षित सदस्य चर का उपयोग करना चाहिए? इसके क्या फायदे हैं और कौन से मुद्दे इसकी वजह बन सकते हैं?
क्या आपको कभी संरक्षित सदस्य चर का उपयोग करना चाहिए? इसके क्या फायदे हैं और कौन से मुद्दे इसकी वजह बन सकते हैं?
जवाबों:
क्या आपको कभी संरक्षित सदस्य चर का उपयोग करना चाहिए?
इस बात पर निर्भर करता है कि आप छिपने की अवस्था के बारे में कितने चुस्त हैं।
यदि कोई डेवलपर साथ आता है और आपकी कक्षा को उपवर्गित करता है तो वे इसे गड़बड़ कर सकते हैं क्योंकि वे इसे पूरी तरह से नहीं समझते हैं। निजी सदस्यों के साथ, सार्वजनिक इंटरफ़ेस के अलावा, वे कार्यान्वयन विशिष्ट विवरण नहीं देख सकते हैं कि कैसे चीजें की जा रही हैं जो आपको बाद में इसे बदलने की सुविधा देती हैं।
आजकल आम भावना यह है कि वे व्युत्पन्न वर्गों और उनके ठिकानों के बीच अनुचित युग्मन का कारण बनते हैं।
संरक्षित तरीकों / संपत्तियों पर उनका कोई विशेष लाभ नहीं है (एक बार जब उन्हें थोड़ा सा प्रदर्शन लाभ हो सकता है), और वे भी एक युग में अधिक उपयोग किए जाते थे जब बहुत गहरी विरासत फैशन में थी, जो इस समय नहीं है।
no particular advantage over protected methods/properties
होना चाहिए no particular advantage over *private* methods/properties
?
super
निर्माण को मूल निर्माणकर्ता को कॉल करने के लिए उपयोग कर सकते हैं ; तब यह मूल श्रेणी में निजी राज्य चर को आरंभ करने का ध्यान रखेगा।
आमतौर पर, अगर किसी चीज़ को जानबूझकर सार्वजनिक नहीं किया जाता है, तो मैं इसे निजी बना देता हूं।
यदि ऐसी स्थिति उत्पन्न होती है, जहाँ मुझे उस निजी चर या विधि की पहुँच किसी व्युत्पन्न वर्ग से करनी है, तो मैं इसे निजी से संरक्षित में बदल देता हूँ।
यह शायद ही कभी होता है - मैं वास्तव में वंशानुक्रम का प्रशंसक नहीं हूं, क्योंकि यह ज्यादातर स्थितियों को मॉडल करने का एक अच्छा तरीका नहीं है। किसी भी दर पर, कोई चिंता नहीं है।
मैं कहूंगा कि यह डेवलपर्स के बहुमत के लिए ठीक है (और शायद इसके बारे में जाने का सबसे अच्छा तरीका है)।
इस मामले का साधारण तथ्य यह है , अगर कुछ अन्य डेवलपर एक साल बाद साथ आते हैं और निर्णय लेते हैं कि उन्हें आपके निजी सदस्य चर तक पहुंच की आवश्यकता है, तो वे बस कोड को संपादित करने, इसे संरक्षित करने के लिए बदलने और अपने व्यवसाय को आगे बढ़ाने के लिए जा रहे हैं।
इसका एकमात्र वास्तविक अपवाद यह है कि यदि आप बाइनरी डीएल के ब्लैक-बॉक्स के रूप में तृतीय पक्षों को शिपिंग करने के व्यवसाय में हैं। इसमें मूल रूप से Microsoft, उन 'कस्टम डेटाग्रिड कंट्रोल' विक्रेताओं, और शायद कुछ अन्य बड़े ऐप शामिल हैं जो एक्स्टेंसिबिलिटी लाइब्रेरी के साथ जहाज करते हैं। जब तक आप उस श्रेणी में नहीं होते हैं, तब तक इस तरह की चिंता करने के लिए समय / प्रयास खर्च करने लायक नहीं है।
मेरे लिए प्रमुख मुद्दा यह है कि एक बार जब आप एक चर को संरक्षित कर लेते हैं, तो आप अपनी श्रेणी में किसी भी विधि को उसके मूल्य पर निर्भर होने की अनुमति नहीं दे सकते , क्योंकि एक उपवर्ग हमेशा इसे सीमा से बाहर रख सकता है।
उदाहरण के लिए, यदि मेरे पास एक वर्ग है जो एक रेंडर योग्य ऑब्जेक्ट की चौड़ाई और ऊंचाई को परिभाषित करता है, और मैं उन चर को संरक्षित करता हूं, तो मैं (उदाहरण के लिए), पहलू अनुपात पर कोई धारणा नहीं बना सकता हूं।
गंभीर रूप से, मैं कभी नहीं कर सकता उस समय किसी भी बिंदु पर उन मान्यताओं बना जो उस कोड को लाइब्रेरी के रूप में जारी किया गया है, भले ही मैं पहलू अनुपात बनाए रखने के लिए अपने निपटान को अपडेट करता हूं, मुझे कोई गारंटी नहीं है कि चर के माध्यम से सेट किए जा रहे हैं या माध्यम से पहुँचा जा रहा है। मौजूदा कोड में गेटर्स।
न ही मेरी कक्षा का कोई उपवर्ग उस गारंटी को चुन सकता है, क्योंकि वे चर मानों को लागू नहीं कर सकते हैं, भले ही वह उनके उपवर्ग का पूरा बिंदु हो ।
उदहारण के लिए:
चरों को निजी बनाने के लिए विवश करके, मैं तब व्यवहार को लागू कर सकता हूं जो मुझे बसने या पाने वालों के माध्यम से चाहिए।
सामान्य तौर पर, मैं आपके संरक्षित सदस्य चर को दुर्लभ मामले में रखूंगा जहां आपका उपयोग करने वाले कोड पर कुल नियंत्रण है। यदि आप एक सार्वजनिक एपीआई बना रहे हैं, तो मैं कभी नहीं कहूंगा। नीचे, हम सदस्य चर को ऑब्जेक्ट की "संपत्ति" के रूप में संदर्भित करेंगे।
निजी सुपर-एक्सेसर्स के बजाय सदस्य चर को संरक्षित करने के बाद आपका सुपरक्लास क्या नहीं कर सकता है:
जब संपत्ति को पढ़ा जा रहा हो तो lazily मक्खी पर एक मूल्य बनाएं। यदि आप एक सुरक्षित गेटर विधि जोड़ते हैं, तो आप आलसी मूल्य बना सकते हैं और इसे वापस पारित कर सकते हैं।
पता करें कि संपत्ति कब संशोधित या हटा दी गई। यह बग का परिचय दे सकता है जब सुपरक्लास उस चर की स्थिति के बारे में धारणा बनाता है। चर के लिए एक संरक्षित सेटर विधि बनाना उस नियंत्रण को बनाए रखता है।
ब्रेकपॉइंट सेट करें या वेरिएबल पढ़ने या लिखे जाने पर डीबग आउटपुट जोड़ें।
उस कोड चर का नाम बदलें जो उस कोड का उपयोग किए बिना उसका उपयोग कर सकता है।
सामान्य तौर पर, मुझे लगता है कि यह दुर्लभ मामला होगा जिसे मैं एक संरक्षित सदस्य चर बनाने की सलाह दूंगा। आप कुछ मिनट बिताने से बेहतर हैं कि संपत्ति प्राप्त करने वाले / बसने वालों के माध्यम से संपत्ति को उजागर करें और घंटों बाद किसी अन्य कोड में बग को ट्रैक करें जो संरक्षित चर को संशोधित करता है। इतना ही नहीं, लेकिन आप पर निर्भर कोड को तोड़ने के बिना भविष्य की कार्यक्षमता (जैसे आलसी लोडिंग) को जोड़ने के खिलाफ बीमा किया जाता है। इसे बाद में करने की अपेक्षा बाद में करना कठिन है।
डिजाइन स्तर पर यह एक संरक्षित संपत्ति का उपयोग करने के लिए उपयुक्त हो सकता है, लेकिन कार्यान्वयन के लिए मुझे इसे एक्सेसर / म्यूटेटर विधियों के बजाय एक संरक्षित सदस्य चर पर मैप करने में कोई फायदा नहीं दिखता है।
संरक्षित सदस्य चर में महत्वपूर्ण नुकसान होते हैं क्योंकि वे प्रभावी रूप से ग्राहक कोड (उप-वर्ग) को आधार वर्ग वर्ग की आंतरिक स्थिति तक पहुंच प्रदान करते हैं। यह आधार वर्ग को अपने आक्रमणकारियों को प्रभावी ढंग से बनाए रखने से रोकता है।
उसी कारण से, संरक्षित सदस्य चर भी सुरक्षित बहु-थ्रेडेड कोड को लिखना अधिक कठिन बनाते हैं जब तक कि निरंतर या एक ही धागे तक सीमित न हो।
गौण / उत्परिवर्ती विधियां रखरखाव के तहत काफी अधिक एपीआई स्थिरता और कार्यान्वयन लचीलापन प्रदान करती हैं।
इसके अलावा, यदि आप एक ओओ शुद्धतावादी हैं, तो वस्तुएं संदेश भेजकर, पढ़ने / स्थापित करने में सहयोग / संवाद करती हैं।
बदले में वे बहुत कम लाभ प्रदान करते हैं। मैं जरूरी नहीं कि उन्हें किसी और के कोड से हटा दूं, लेकिन मैं खुद उनका इस्तेमाल नहीं करता।
अधिकांश समय, संरक्षित उपयोग करना खतरनाक होता है क्योंकि आप अपनी कक्षा के कुछ हद तक इनकैप्सुलेशन को तोड़ देते हैं, जो कि खराब रूप से डिज़ाइन किए गए वर्ग द्वारा टूट सकता है।
लेकिन मेरे पास एक अच्छा उदाहरण है: मान लीजिए कि आप कुछ प्रकार के जेनेरिक कंटेनर ले सकते हैं। इसका आंतरिक कार्यान्वयन और आंतरिक एक्सेसर्स हैं। लेकिन आपको इसके डेटा तक कम से कम 3 सार्वजनिक पहुंच प्रदान करने की आवश्यकता है: नक्शा, हैश_मैप, वेक्टर-लाइक। फिर आपके पास कुछ ऐसा है:
template <typename T, typename TContainer>
class Base
{
// etc.
protected
TContainer container ;
}
template <typename Key, typename T>
class DerivedMap : public Base<T, std::map<Key, T> > { /* etc. */ }
template <typename Key, typename T>
class DerivedHashMap : public Base<T, std::hash_map<Key, T> > { /* etc. */ }
template <typename T>
class DerivedVector : public Base<T, std::vector<T> > { /* etc. */ }
मैंने एक महीने से भी कम समय पहले इस तरह के कोड का इस्तेमाल किया था (इसलिए कोड मेमोरी से है)। कुछ सोच के बाद, मेरा मानना है कि जबकि जेनेरिक बेस कंटेनर एक अमूर्त वर्ग होना चाहिए, भले ही यह काफी अच्छी तरह से रह सकता है, क्योंकि सीधे बेस का उपयोग करना एक ऐसा दर्द होगा, जिसे मना किया जाना चाहिए।
सारांश इस प्रकार, आपने व्युत्पन्न वर्ग द्वारा उपयोग किए गए डेटा की रक्षा की है। फिर भी, हमें इस बात का ध्यान रखना चाहिए कि आधार वर्ग अमूर्त होना चाहिए।
protected
से अधिक नहीं है public
। मैं गलत साबित होने को तैयार हूं। आपको बस एक संरक्षित सदस्य के साथ एक वर्ग लिखना है और मुझे इसे संशोधित करने से रोकना है। स्पष्ट रूप से वर्ग को गैर-अंतिम होना चाहिए, क्योंकि संरक्षित उपयोग करने का पूरा बिंदु वंशानुक्रम के लिए है। या तो कुछ एनकैप्सुलेटेड है, या यह नहीं है। कोई बीच में नहीं है।
संक्षेप में, हाँ।
संरक्षित सदस्य चर किसी भी उप-वर्गों के साथ-साथ एक ही पैकेज में किसी भी वर्ग से चर तक पहुंच की अनुमति देते हैं। यह अत्यधिक उपयोगी हो सकता है, विशेष रूप से केवल-पढ़ने के लिए डेटा के लिए। मुझे विश्वास नहीं है कि वे कभी भी आवश्यक होते हैं, क्योंकि एक संरक्षित सदस्य चर के किसी भी उपयोग को निजी सदस्य चर और कुछ गेटर्स और सेटर्स का उपयोग करके दोहराया जा सकता है।
.Net पहुँच संशोधक के बारे में विस्तृत जानकारी के लिए यहाँ जाएँ
संरक्षित सदस्य चर के कोई वास्तविक लाभ या नुकसान नहीं हैं, यह एक सवाल है कि आपको अपनी विशिष्ट स्थिति में क्या चाहिए। सामान्य तौर पर यह सदस्य चर को निजी घोषित करने और संपत्तियों के माध्यम से बाहरी पहुंच को सक्षम करने के लिए अभ्यास को स्वीकार किया जाता है। इसके अलावा, कुछ उपकरण (जैसे कुछ ओ / आर मैपर्स) ऑब्जेक्ट डेटा को गुणों द्वारा दर्शाए जाने की अपेक्षा करते हैं और सार्वजनिक या संरक्षित सदस्य चर को नहीं पहचानते हैं। लेकिन अगर आप जानते हैं कि आप अपने उपवर्गों (और केवल अपने उपवर्गों) को एक निश्चित चर तक पहुंचना चाहते हैं, तो इसे संरक्षित घोषित नहीं करने का कोई कारण नहीं है।