मुझे याद है कि विश्वविद्यालय में C ++ सीखने के दौरान मेरे लेक्चरर के साथ भी ऐसा ही तर्क था। जब मैं एक चर सार्वजनिक कर सकता था तो मैं बस गेटर्स और सेटर का उपयोग करने की बात नहीं देख सकता था। मैं अब वर्षों के अनुभव के साथ बेहतर समझ रहा हूं और मैंने "एनकैप्सुलेशन को बनाए रखने के लिए" कहने के बजाय एक बेहतर कारण सीखा है।
गेटर्स और सेटर्स को परिभाषित करके, आप एक सुसंगत इंटरफ़ेस प्रदान करेंगे ताकि यदि आप अपने कार्यान्वयन को बदलना चाहते हैं, तो आपको आश्रित कोड को तोड़ने की संभावना कम है। यह विशेष रूप से महत्वपूर्ण है जब आप कक्षाएं एक एपीआई के माध्यम से उजागर होते हैं और अन्य एप्लिकेशन में या तीसरे पक्ष द्वारा उपयोग की जाती हैं। तो उस सामान के बारे में क्या जो गटर या सेटर में जाता है?
आम तौर पर मूल्य तक पहुंचने के लिए सरल डंबड-डाउन पैशट्रॉफ़ के रूप में गेटर्स को बेहतर तरीके से लागू किया जाता है क्योंकि इससे उनके व्यवहार का अनुमान लगाया जा सकता है। मैं आमतौर पर कहता हूं, क्योंकि मैंने ऐसे मामलों को देखा है जहां गणना या सशर्त कोड द्वारा हेरफेर किए गए मूल्यों तक पहुंचने के लिए गेटर्स का उपयोग किया गया है। आम तौर पर इतना अच्छा नहीं है यदि आप डिजाइन समय पर उपयोग के लिए दृश्य घटक बना रहे हैं, लेकिन रन के समय में आसान प्रतीत होता है। हालांकि, इसके बीच और किसी सरल विधि का उपयोग करने के बीच कोई वास्तविक अंतर नहीं है, सिवाय इसके कि जब आप किसी विधि का उपयोग करते हैं, तो आप आमतौर पर एक विधि को अधिक उचित रूप से नाम देने की संभावना रखते हैं ताकि कोड को पढ़ते समय "गेट्टर" की कार्यक्षमता अधिक स्पष्ट हो।
निम्नलिखित की तुलना करें:
int aValue = MyClass.Value;
तथा
int aValue = MyClass.CalculateValue();
दूसरा विकल्प यह स्पष्ट करता है कि मूल्य की गणना की जा रही है, जबकि पहला उदाहरण आपको बताता है कि आप केवल मूल्य के बारे में कुछ भी जाने बिना एक मूल्य वापस कर रहे हैं।
आप शायद तर्क दे सकते हैं कि निम्नलिखित स्पष्ट होगा:
int aValue = MyClass.CalculatedValue;
समस्या यह है कि आप मान रहे हैं कि मूल्य पहले ही कहीं और हेरफेर किया गया है। इसलिए एक गॉटर के मामले में, जबकि आप यह मान सकते हैं कि जब आप एक मूल्य वापस कर रहे हैं तो कुछ और हो सकता है, संपत्ति के संदर्भ में ऐसी चीजों को स्पष्ट करना मुश्किल है, और संपत्ति के नाम में कभी भी क्रियाएं नहीं होनी चाहिए। अन्यथा यह एक नज़र में समझना मुश्किल हो जाता है कि क्या उपयोग किया गया नाम अभिगम के समय कोष्ठक से सजाया जाना चाहिए।
सेटर्स हालांकि थोड़ा अलग मामला है। यह पूरी तरह से उचित है कि एक संपत्ति के लिए प्रस्तुत किए जा रहे डेटा को मान्य करने के लिए एक सेटर कुछ अतिरिक्त प्रसंस्करण प्रदान करता है, अगर मूल्य निर्धारित करने पर अपवाद फेंकना संपत्ति की परिभाषित सीमाओं का उल्लंघन करेगा। समस्या यह है कि कुछ डेवलपर्स को बसने के लिए प्रसंस्करण को जोड़ने के साथ है, लेकिन यह है कि सेटर को हमेशा थोड़ा और अधिक करने का प्रलोभन होता है, जैसे कि किसी तरह से गणना या डेटा का हेरफेर करना। यह वह जगह है जहां आप दुष्प्रभाव प्राप्त कर सकते हैं जो कुछ मामलों में अप्रत्याशित या अवांछनीय हो सकता है।
बसने वालों के मामले में, मैं हमेशा अंगूठे का एक सरल नियम लागू करता हूं, जो डेटा के लिए जितना संभव हो उतना कम करना है। उदाहरण के लिए, मैं आमतौर पर या तो सीमा परीक्षण की अनुमति देता हूं, और गोलाई देता हूं ताकि मैं दोनों अपवादों को उचित होने पर उठा सकूं, या अनावश्यक अपवादों से बच सकूं जहां उन्हें समझदारी से टाला जा सके। फ़्लोटिंग पॉइंट गुण एक अच्छा उदाहरण है जहाँ आप अपवाद बढ़ाने से बचने के लिए अत्यधिक दशमलव स्थानों को गोल करना चाह सकते हैं, जबकि कुछ अतिरिक्त दशमलव स्थानों के साथ रेंज मानों को अभी भी प्रवेश करने की अनुमति देते हैं।
यदि आप सेटर इनपुट के कुछ प्रकार के हेरफेर को लागू करते हैं, तो आपको गेट्टर के साथ भी यही समस्या होती है, कि दूसरों को यह जानने की अनुमति देना मुश्किल है कि सेटर केवल नामकरण करके क्या कर रहा है। उदाहरण के लिए:
MyClass.Value = 12345;
क्या यह आपको इस बारे में कुछ बताता है कि जब यह सेटर को दिया जाता है तो मूल्य का क्या होने वाला है?
कैसा रहेगा:
MyClass.RoundValueToNearestThousand(12345);
दूसरा उदाहरण आपको बताता है कि आपके डेटा का वास्तव में क्या होने जा रहा है, जबकि पहला आपको यह नहीं बताएगा कि क्या आप मूल्य को मनमाने ढंग से संशोधित करने जा रहे हैं। कोड पढ़ते समय, दूसरा उदाहरण इसके उद्देश्य और कार्य में अधिक स्पष्ट होगा।
क्या मैं सही हूं कि यह पहली जगह में गेटर्स और सेटर होने के उद्देश्य को पूरी तरह से हरा देगा और सत्यापन और अन्य लॉजिक (अजीब दुष्प्रभावों के बिना) को अनुमति दी जानी चाहिए?
गेटर्स और सेटर "शुद्धता" की खातिर इनकैप्सुलेशन के बारे में नहीं है, लेकिन कोड को आसानी से रिफलेक्ट किए जाने की अनुमति देने के बारे में क्लास के इंटरफेस में बदलाव किए बिना आसानी से रिफैक्ट किया जा सकता है। एक सेटर में सत्यापन पूरी तरह से उपयुक्त है, हालांकि एक छोटा जोखिम यह है कि सत्यापन के लिए एक परिवर्तन कॉलिंग कोड के साथ संगतता को तोड़ सकता है यदि कॉलिंग कोड एक विशेष तरीके से होने वाले सत्यापन पर निर्भर करता है। यह आम तौर पर दुर्लभ और अपेक्षाकृत कम जोखिम वाली स्थिति है, लेकिन इसे पूर्णता के लिए नोट किया जाना चाहिए।
सत्यापन कब होना चाहिए?
मूल्यांकन वास्तव में मूल्य निर्धारित करने से पहले सेटर के संदर्भ में होना चाहिए। यह सुनिश्चित करता है कि यदि कोई अपवाद फेंका जाता है, तो आपकी वस्तु की स्थिति नहीं बदलेगी और संभवतः उसके डेटा को अमान्य कर देगी। मुझे आम तौर पर मान्यता को एक अलग विधि में सौंपना बेहतर लगता है, जो सेटर कोड को अपेक्षाकृत अछूता रखने के लिए, सेटर के भीतर कहा जाने वाला पहला काम होगा।
क्या एक सेटर को मान बदलने की अनुमति दी जाती है (हो सकता है कि वैध मूल्य को कुछ कैनोनिकल आंतरिक प्रतिनिधित्व में बदल दें)?
बहुत दुर्लभ मामलों में, शायद। सामान्य तौर पर, यह शायद बेहतर नहीं है। यह एक अन्य विधि के लिए सबसे अच्छी बात है।