क्या आपको कभी संरक्षित सदस्य चर का उपयोग करना चाहिए?


97

क्या आपको कभी संरक्षित सदस्य चर का उपयोग करना चाहिए? इसके क्या फायदे हैं और कौन से मुद्दे इसकी वजह बन सकते हैं?

जवाबों:


73

क्या आपको कभी संरक्षित सदस्य चर का उपयोग करना चाहिए?

इस बात पर निर्भर करता है कि आप छिपने की अवस्था के बारे में कितने चुस्त हैं।

  • यदि आप आंतरिक स्थिति की कोई लीक नहीं चाहते हैं, तो अपने सभी सदस्य चर को निजी घोषित करना एक रास्ता है।
  • यदि आप वास्तव में परवाह नहीं करते हैं कि उपवर्ग आंतरिक स्थिति तक पहुंच सकते हैं, तो संरक्षित पर्याप्त है।

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


1
क्या आप गेट / सेट विधि के साथ निजी चर बनाम संरक्षित चर के प्रदर्शन पर टिप्पणी कर सकते हैं?
जेक

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

23
@ जेक: आपको प्रदर्शन के अनुमानों के आधार पर कभी भी निर्णय नहीं लेना चाहिए। आप अपने हिसाब से डिजाइन निर्णय लेते हैं जो आपको लगता है कि सबसे अच्छा डिजाइन है और केवल तभी जब आप वास्तविक जीवन की रूपरेखा को अपने डिजाइन में अड़चन दिखाते हैं, आप इसे ठीक करते हैं। आमतौर पर अगर डिजाइन ध्वनि है, तो प्रदर्शन अच्छा है।
मेक्की

निजी सदस्यों के साथ, सार्वजनिक इंटरफ़ेस के अलावा, वे कार्यान्वयन विशिष्ट विवरण नहीं देख सकते हैं वे सिर्फ कक्षा खोल सकते हैं और इसे देख सकते हैं, ताकि कोई मतलब न हो!
ब्लैक

2
@ ब्लेक क्लियरली एलेन का मतलब था कि वे उन सदस्यों तक पहुंच नहीं सकते हैं और इसलिए उनके खिलाफ कोड का निर्माण नहीं कर सकते हैं, बाद में संरक्षित सदस्यों को हटाने / बदलने के लिए कक्षा के लेखक को स्वतंत्र छोड़ सकते हैं। (ज़ाहिर है, पिम्पल मुहावरा उन्हें नेत्रहीन और हेडर सहित अनुवाद इकाइयों से छिपाने में सक्षम होगा।)
अंडरस्कोर_ड

31

आजकल आम भावना यह है कि वे व्युत्पन्न वर्गों और उनके ठिकानों के बीच अनुचित युग्मन का कारण बनते हैं।

संरक्षित तरीकों / संपत्तियों पर उनका कोई विशेष लाभ नहीं है (एक बार जब उन्हें थोड़ा सा प्रदर्शन लाभ हो सकता है), और वे भी एक युग में अधिक उपयोग किए जाते थे जब बहुत गहरी विरासत फैशन में थी, जो इस समय नहीं है।


2
नहीं no particular advantage over protected methods/propertiesहोना चाहिए no particular advantage over *private* methods/properties?
पेंघे गेंग

नहीं, क्योंकि मैं व्युत्पन्न वर्गों और उनके ठिकानों के बीच संचार के विभिन्न तरीकों के फायदे / नुकसान के बारे में बात कर रहा हूं - इन सभी तकनीकों को 'संरक्षित' किया जाएगा - अंतर यह है कि क्या वे सदस्य चर (क्षेत्र) या गुण / तरीके (हैं) अर्थात किसी प्रकार का उप-भाग)।
विल डीन

1
त्वरित स्पष्टीकरण के लिए धन्यवाद। मुझे खुशी है कि 6 साल पुरानी पोस्ट के लिए मेरे प्रश्न के मूल पोस्टर का एक घंटे में जवाब होगा। आपको नहीं लगता कि यह अधिकांश अन्य ऑनलाइन मंचों में हो सकता है :)
पेंघ गेंग

9
इससे भी अधिक उल्लेखनीय यह है कि मैं वास्तव में उस समय की राशि से खुद को सहमत करता हूं ...
डीन

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

31

आमतौर पर, अगर किसी चीज़ को जानबूझकर सार्वजनिक नहीं किया जाता है, तो मैं इसे निजी बना देता हूं।

यदि ऐसी स्थिति उत्पन्न होती है, जहाँ मुझे उस निजी चर या विधि की पहुँच किसी व्युत्पन्न वर्ग से करनी है, तो मैं इसे निजी से संरक्षित में बदल देता हूँ।

यह शायद ही कभी होता है - मैं वास्तव में वंशानुक्रम का प्रशंसक नहीं हूं, क्योंकि यह ज्यादातर स्थितियों को मॉडल करने का एक अच्छा तरीका नहीं है। किसी भी दर पर, कोई चिंता नहीं है।

मैं कहूंगा कि यह डेवलपर्स के बहुमत के लिए ठीक है (और शायद इसके बारे में जाने का सबसे अच्छा तरीका है)।

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

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


8

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

उदाहरण के लिए, यदि मेरे पास एक वर्ग है जो एक रेंडर योग्य ऑब्जेक्ट की चौड़ाई और ऊंचाई को परिभाषित करता है, और मैं उन चर को संरक्षित करता हूं, तो मैं (उदाहरण के लिए), पहलू अनुपात पर कोई धारणा नहीं बना सकता हूं।

गंभीर रूप से, मैं कभी नहीं कर सकता उस समय किसी भी बिंदु पर उन मान्यताओं बना जो उस कोड को लाइब्रेरी के रूप में जारी किया गया है, भले ही मैं पहलू अनुपात बनाए रखने के लिए अपने निपटान को अपडेट करता हूं, मुझे कोई गारंटी नहीं है कि चर के माध्यम से सेट किए जा रहे हैं या माध्यम से पहुँचा जा रहा है। मौजूदा कोड में गेटर्स।

न ही मेरी कक्षा का कोई उपवर्ग उस गारंटी को चुन सकता है, क्योंकि वे चर मानों को लागू नहीं कर सकते हैं, भले ही वह उनके उपवर्ग का पूरा बिंदु हो

उदहारण के लिए:

  • मेरे पास एक आयत वर्ग है जिसकी चौड़ाई और ऊंचाई संरक्षित चर के रूप में संग्रहीत की जा रही है।
  • एक स्पष्ट उप-वर्ग (मेरे संदर्भ में) एक "डिस्प्लेड्रेक्टंगल" वर्ग है, जहां एकमात्र अंतर यह है कि मैं चित्रमय प्रदर्शन के लिए मान्य मानों की चौड़ाई और ऊंचाइयों को प्रतिबंधित करता हूं।
  • लेकिन यह अब असंभव है , क्योंकि मेरा DisplayedRectangle वर्ग वास्तव में उन मूल्यों को बाधित नहीं कर सकता है , क्योंकि इसका कोई भी उपवर्ग सीधे मानों को ओवरराइड कर सकता है, जबकि अभी भी DisplayedRectangle के रूप में माना जा रहा है।

चरों को निजी बनाने के लिए विवश करके, मैं तब व्यवहार को लागू कर सकता हूं जो मुझे बसने या पाने वालों के माध्यम से चाहिए।


7

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

निजी सुपर-एक्सेसर्स के बजाय सदस्य चर को संरक्षित करने के बाद आपका सुपरक्लास क्या नहीं कर सकता है:

  1. जब संपत्ति को पढ़ा जा रहा हो तो lazily मक्खी पर एक मूल्य बनाएं। यदि आप एक सुरक्षित गेटर विधि जोड़ते हैं, तो आप आलसी मूल्य बना सकते हैं और इसे वापस पारित कर सकते हैं।

  2. पता करें कि संपत्ति कब संशोधित या हटा दी गई। यह बग का परिचय दे सकता है जब सुपरक्लास उस चर की स्थिति के बारे में धारणा बनाता है। चर के लिए एक संरक्षित सेटर विधि बनाना उस नियंत्रण को बनाए रखता है।

  3. ब्रेकपॉइंट सेट करें या वेरिएबल पढ़ने या लिखे जाने पर डीबग आउटपुट जोड़ें।

  4. उस कोड चर का नाम बदलें जो उस कोड का उपयोग किए बिना उसका उपयोग कर सकता है।

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


7

डिजाइन स्तर पर यह एक संरक्षित संपत्ति का उपयोग करने के लिए उपयुक्त हो सकता है, लेकिन कार्यान्वयन के लिए मुझे इसे एक्सेसर / म्यूटेटर विधियों के बजाय एक संरक्षित सदस्य चर पर मैप करने में कोई फायदा नहीं दिखता है।

संरक्षित सदस्य चर में महत्वपूर्ण नुकसान होते हैं क्योंकि वे प्रभावी रूप से ग्राहक कोड (उप-वर्ग) को आधार वर्ग वर्ग की आंतरिक स्थिति तक पहुंच प्रदान करते हैं। यह आधार वर्ग को अपने आक्रमणकारियों को प्रभावी ढंग से बनाए रखने से रोकता है।

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

गौण / उत्परिवर्ती विधियां रखरखाव के तहत काफी अधिक एपीआई स्थिरता और कार्यान्वयन लचीलापन प्रदान करती हैं।

इसके अलावा, यदि आप एक ओओ शुद्धतावादी हैं, तो वस्तुएं संदेश भेजकर, पढ़ने / स्थापित करने में सहयोग / संवाद करती हैं।

बदले में वे बहुत कम लाभ प्रदान करते हैं। मैं जरूरी नहीं कि उन्हें किसी और के कोड से हटा दूं, लेकिन मैं खुद उनका इस्तेमाल नहीं करता।


4

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

लेकिन मेरे पास एक अच्छा उदाहरण है: मान लीजिए कि आप कुछ प्रकार के जेनेरिक कंटेनर ले सकते हैं। इसका आंतरिक कार्यान्वयन और आंतरिक एक्सेसर्स हैं। लेकिन आपको इसके डेटा तक कम से कम 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. */ }

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

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


यह सार्वजनिक सदस्यों की तुलना में अब इनकैप्सुलेशन को नहीं तोड़ता है। यह कहने के लिए एक सेटिंग है कि व्युत्पन्न वर्ग वर्ग के राज्य का उपयोग कर सकते हैं जो वर्ग के उपयोगकर्ताओं के संपर्क में नहीं है।
gbjbaanb

@ जीबीजैनब: आप खुद का विरोध कर रहे हैं "यह अब इनकैप्सुलेशन को नहीं तोड़ता है, सार्वजनिक सदस्यों की तुलना में" केवल "अलग है" व्युत्पन्न वर्ग वर्ग 'राज्य' का उपयोग कर सकते हैं। "संरक्षित" सार्वजनिक और निजी के बीच का मध्य है। इसलिए "संरक्षित [...] कुछ हद तक इनकैप्सुलेशन टूट जाता है" अभी भी सही है ...
पेर्सबल

वास्तव में, सी ++ भाषा में, std :: stack जैसे कंटेनर एडेप्टर अंतर्निहित कंटेनर ऑब्जेक्ट को "c" नामक एक संरक्षित चर के साथ उजागर करेंगे।
जोहान्स शाउब -

मुझे पता है कि यह पोस्ट काफी पुरानी है, लेकिन मुझे इसमें झंकार करने की आवश्यकता है। आप कुछ हद तक "एनकैप्सुलेशन" को नहीं तोड़ते हैं, आप इसे पूरी तरह से तोड़ देते हैं। protectedसे अधिक नहीं है public। मैं गलत साबित होने को तैयार हूं। आपको बस एक संरक्षित सदस्य के साथ एक वर्ग लिखना है और मुझे इसे संशोधित करने से रोकना है। स्पष्ट रूप से वर्ग को गैर-अंतिम होना चाहिए, क्योंकि संरक्षित उपयोग करने का पूरा बिंदु वंशानुक्रम के लिए है। या तो कुछ एनकैप्सुलेटेड है, या यह नहीं है। कोई बीच में नहीं है।
ताकाहन

3

संक्षेप में, हाँ।

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


1
इसके विपरीत, निजी सदस्य चर की भी कभी आवश्यकता नहीं होती है; सार्वजनिक किसी भी उपयोग के लिए पर्याप्त है।
एलिस

3

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


2

.Net पहुँच संशोधक के बारे में विस्तृत जानकारी के लिए यहाँ जाएँ

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


एक चर का उपयोग करने के लिए उपवर्गों को चाहने से बहुत अलग है कि वे इसे स्वतंत्र रूप से बदलने में सक्षम होना चाहते हैं । यह संरक्षित चर के खिलाफ मुख्य तर्कों में से एक है: अब आपका आधार वर्ग अपने किसी भी आक्रमणकारी को धारण नहीं कर सकता है, क्योंकि कोई भी व्युत्पन्न वर्ग संरक्षित सदस्यों के साथ बिल्कुल कुछ भी कर सकता है। यही उनके खिलाफ मुख्य तर्क है। यदि उन्हें सिर्फ डेटा एक्सेस करने की आवश्यकता है , तो ... एक एक्सेसर लिखें। : पी (मैं संरक्षित चर का उपयोग करता हूं, हालांकि शायद मुझे जितना चाहिए, और मैं कट-डाउन करने की कोशिश कर रहा हूं!)
अंडरस्कोर_ड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.