निजी गेटर्स के बजाय सार्वजनिक फाइनल का उपयोग करना


51

मैं इस तरह लिखे गए अधिकांश अपरिवर्तनीय POJOs देखता हूं:

public class MyObject {
    private final String foo;
    private final int bar;

    public MyObject(String foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    }

    public String getFoo() {
        return foo;
    }

    public int getBar() {
        return bar;
    }
}

फिर भी मैं उन्हें इस तरह लिखना चाहता हूं:

public class MyObject {
    public final String foo;
    public final int bar;

    public MyObject(String foo, int bar) {
        this.foo = foo;
        this.bar = bar;
    }
}

ध्यान दें कि संदर्भ अंतिम हैं, इसलिए ऑब्जेक्ट अभी भी अपरिवर्तनीय है। यह मुझे कम कोड लिखने देता है और कम (5 वर्णों द्वारा: getऔर ()) पहुंच की अनुमति देता है ।

एकमात्र नुकसान जो मैं देख सकता हूं, यदि आप getFoo()कुछ पागल करने के लिए सड़क के कार्यान्वयन को बदलना चाहते हैं , तो आप नहीं कर सकते। लेकिन वास्तविक रूप से, ऐसा कभी नहीं होता है क्योंकि वस्तु अपरिवर्तनीय है; आप इन्स्टेन्शियशन दौरान सत्यापित कर सकते हैं, इन्स्टेन्शियशन दौरान अपरिवर्तनीय बचाव की मुद्रा में प्रतिलिपि बनाने (देखें अमरूद के ImmutableListउदाहरण के लिए), और पाने fooया barके लिए तैयार वस्तुओं getकॉल।

क्या मुझे कोई कमी है?

संपादित करें

मुझे लगता है कि एक और नुकसान मुझे याद आ रहा है कि सीरियलाइज़ेशन लाइब्रेरियों के साथ शुरू होने वाले तरीकों पर प्रतिबिंब का उपयोग getकर रहा है is, लेकिन यह एक बहुत ही भयानक अभ्यास है ...


क्या बकवास है? finalएक चर वस्तु को अपरिवर्तनीय नहीं बनाता है। मैं आमतौर पर एक डिज़ाइन का उपयोग करता हूं जहां मैं finalकॉलबैक बनाने से पहले फ़ील्ड को परिभाषित करता हूं ताकि कॉलबैक उन फ़ील्ड तक पहुंच सके। यह निश्चित रूप से किसी भी setXतरीके सहित सभी तरीकों को कॉल कर सकता है ।
टॉमैटो ज़ाटो

@ TomášZato पर कोई setX तरीकों रहे हैं String, intया MyObject। पहले संस्करण में, finalकेवल यह सुनिश्चित करना है कि कक्षा के भीतर कंस्ट्रक्टर के अलावा अन्य तरीके bar = 7;उदाहरण के लिए प्रयास न करें । दूसरे संस्करण में, finalउपभोक्ताओं को ऐसा करने से रोकने के लिए आवश्यक है MyObject x = new MyObject("hi", 5); x.bar = 7;:।
कोरी केंडल

1
वैसे आपके " नोट संदर्भ अंतिम हैं, इसलिए Objectअभी भी अपरिवर्तनीय है। " भ्रामक है - इस तरह से यह प्रतीत होता है कि आपको लगता है कि कोई भी final Objectअपरिवर्तनीय है, जो यह नहीं है। गलतफहमी के लिए खेद है।
टॉमेज़ ज़ाटो

3
यदि अंतर्निहित मान परिवर्तनशील थे, तो निजी + एक्सेसर्स सड़क या तो इसे रोक नहीं पाएगी - myObj.getFoo().setFrob(...)
बेनी चेर्नियाव्स्की-पास्किन

जवाबों:


38

चार नुकसान जो मैं सोच सकता हूं:

  1. यदि आप एक ही इकाई का रीड-ओनली और म्यूटेबल फॉर्म रखना चाहते हैं, तो एक सामान्य पैटर्न में एक अपरिवर्तनीय वर्ग एंटिटी है जो केवल संरक्षित सदस्य चर के साथ एक्सेसर्स को उजागर करता है, फिर एक MutableEntity बनाएं जो इसे बढ़ाता है और बसने वाला जोड़ता है। आपका संस्करण इसे रोकता है।
  2. गेटर्स और सेटर का उपयोग JavaBeans सम्मेलन का पालन करता है। यदि आप अपने वर्ग का उपयोग संपत्ति आधारित तकनीकों में बीन के रूप में करना चाहते हैं, जैसे कि JSTL या EL, तो आपको सार्वजनिक गेटर्स को उजागर करने की आवश्यकता है।
  3. यदि आप कभी भी मूल्यों को प्राप्त करने के लिए कार्यान्वयन को बदलना चाहते हैं या उन्हें डेटाबेस में देखना चाहते हैं, तो आपको ग्राहक कोड को रिफलेक्टर करना होगा। एक गौण / उत्परिवर्ती दृष्टिकोण आपको केवल कार्यान्वयन को बदलने की अनुमति देता है।
  4. कम से कम विस्मय - जब मैं सार्वजनिक उदाहरण चर देखता हूं, तो मैं तुरंत देखता हूं कि कौन इसे उत्परिवर्तित कर सकता है और चिंता करता है कि मैं पेंडोरा का बॉक्स खोल रहा हूं क्योंकि एनकैप्सुलेशन खो गया है। http://en.wikipedia.org/wiki/Principle_of_least_astonishment

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


3
शानदार जवाब; मेरी उनमें से कुछ के साथ असहमति है, लेकिन मुझे यकीन नहीं है कि यह साइट चर्चा के लिए सबसे अच्छा मंच है। संक्षेप में, 1) मैं अन्य लोगों को उस परिवर्तनशील रूप का उपयोग करके तोड़ सकता हूं, जहां वे यह मानते हैं कि यह अपरिवर्तनीय है (शायद मुझे अपने उदाहरणों में कक्षा में अंतिम जोड़ना चाहिए), 2) मैं सहमत हूं, 3) मेरा तर्क है कि इसमें अब कोई पीओजेओ नहीं है मामला, 4) मैं अभी के लिए सहमत हूं, लेकिन उम्मीद है कि इस तरह की चर्चा कम से कम आश्चर्यजनक रूप से बदल सकती है :)।
कोरी केंडल

2
5) आप सुरक्षित रूप से उत्परिवर्तनीय वर्गों / प्रकारों - जैसे सरणियों को सुरक्षित रूप से उजागर नहीं कर सकते। सुरक्षित तरीका यह है कि हर बार एक गेटर से एक कॉपी लौटा दी जाए।
क्लॉकवर्क-म्यूजियम

@ घड़ी-संग्रहालय आप कर सकते हैं, अगर आप मानते हैं कि लोग बेवकूफ नहीं हैं। जब कुछObj.thisList.add () एक्सेस कर रहे हैं तो यह स्पष्ट है कि आप कुछ अन्य ऑब्जेक्ट्स को संशोधित कर रहे हैं। SomeObj.getThisList () के साथ जोड़ें () यह अज्ञात है। आपको दस्तावेज़ीकरण पूछने या स्रोत देखने की आवश्यकता है, लेकिन विधि घोषणा से अकेले यह बताना असंभव है।
kritzikratzi

2
@kritzikratzi - समस्या यह है कि आप गारंटी नहीं दे सकते कि आपका कोड बेवकूफों में नहीं चलेगा। कुछ समय यह होगा (यहां तक कि अपने आप को किया जा रहा है जो अंत हो सकता है!), और आश्चर्य की बात है एक विशाल समस्या हो सकती है।
क्लॉकवर्क-म्यूजियम

1
वैसे, किसी अपरिवर्तनीय प्रकार से किसी भी परिवर्तनशील प्रकार को जन्म देना स्वाभाविक रूप से गलत है। याद रखें कि एक अपरिवर्तनीय प्रकार गारंटी देता है "मैं नहीं बदलता। कभी।"
डिडुप्लिकेटर

26

गेटर्स से छुटकारा / बसने के लिए भी, और आप ठीक हैं!

यह जावा प्रोग्रामर के बीच एक अत्यधिक विवादास्पद विषय है।

वैसे भी, वहाँ दो बैठने की जगह है जहाँ मैं सार्वजनिक चर का उपयोग करता हूँ (!) पाने वालों / बसने वालों के लिए:

  1. सार्वजनिक फाइनल मेरे लिए यह संकेत "मैं अपरिवर्तनीय हूँ" सिर्फ एक गटर से बेहतर। अधिकांश आईडीई स्वतः पूर्णता के दौरान 'एफ' के साथ अंतिम संशोधक का संकेत देंगे। गेटर्स / सेटर्स के विपरीत, जहां आपको सेटएक्सएक्सएक्सएक्स की अनुपस्थिति की खोज करनी होगी।
  2. सार्वजनिक गैर-अंतिम मैं इसे डेटा वर्गों के लिए प्यार करता हूं। मैं सार्वजनिक रूप से सभी क्षेत्रों को उजागर करता हूं। कोई गेटर्स, सेटर, कंस्ट्रक्टर नहीं। कुछ भी नहीं। एक पूजो से कम। मेरे लिए यह तुरंत संकेत देता है "देखो, मैं गूंगा हूं। मैं डेटा रखता हूं, बस इतना ही। यह मेरे अंदर सही डेटा डालने का काम है"। Gson / JAXB / आदि। इन कक्षाओं को ठीक से संभालें। वे लिखने के लिए आनंदित हैं। उनके उद्देश्य या क्षमताओं के बारे में कोई संदेह नहीं है। और सबसे महत्वपूर्ण बात: आप जानते हैं कि जब आप एक चर को बदलते हैं तो कोई दुष्प्रभाव नहीं होता है। IMHO का परिणाम कुछ अस्पष्टताओं के साथ बहुत संक्षिप्त डेटा मॉडल में होता है, जबकि गेटर्स और सेटर्स में यह बहुत बड़ी समस्या होती है जहां कभी-कभी उनके अंदर जादू होता है।

5
एक बार थोड़ी देर में कुछ पवित्रता देखकर अच्छा लगा :)
नवीन

2
दिन आने तक जहां आपका मॉडल विकसित होता है और पुराने क्षेत्रों में से एक अब दूसरे से प्राप्त किया जा सकता है। चूंकि आप पीछे की संगतता को बनाए रखना चाहते हैं, इसलिए पुराना क्षेत्र बना रहना चाहिए, लेकिन केवल गेट्टर और सेटर कोड को बदलने के बजाय आपको हर जगह बदलना होगा, जहां इस पुराने क्षेत्र का उपयोग यह सुनिश्चित करने के लिए किया गया था कि यह नए मॉडल प्रतिनिधित्व का पालन करता है। लिखने में आसान .. हाँ यकीन है ... लंबे समय तक बनाए रखने के लिए दुःस्वप्न ... यही कारण है कि हमारे पास सी # प्रॉपर्टी एक्सेसर्स में गेट्टर / सेटर या बेहतर हैं।
न्यूटॉपियन

9

आम आदमी के शब्दों में:

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

6
यह इनकैप्सुलेशन का उल्लंघन कैसे है? दोनों संस्करण बाहरी दुनिया के लिए एक-दूसरे (केवल पढ़ने के लिए उपयोग) के रूप में सामने आ रहे हैं। आप परिवर्तन के कठिन युग्मन और अनम्यता के बारे में सही हैं, हालांकि, मैं यह तर्क नहीं दूंगा।
KChaloux

4
@Khaloux आप "कोड के संकलन में विफल होने और इसे ठीक करने में समय बर्बाद करने के लिए" के साथ "एनकैप्सुलेशन उल्लंघन" को भ्रमित करते हैं, एक पहले होता है। दूसरा बाद में होता है। यह स्पष्ट करने के लिए: वर्तमान में पहले से ही एनकैप्सुलेशन का उल्लंघन किया जाता है। आपकी कक्षा के लोगों की वर्तमान समय में कमी नहीं है। लेकिन अगर भविष्य में क्लास में बदलाव होता है तो क्लाइंट कोड भविष्य में टूट जाएगा, क्योंकि अतीत में इनकैप्सुलेशन टूट गया था। एन्कैप्सुलेशन की कमी के कारण दो अलग-अलग "ब्रेक" हैं, आज एनकैप्सुलेशन, कल क्लाइंट कोड।
ट्यूलेंस कोर्डोवा

8
तकनीकी रूप से, जब आप गेटर्स / आदि का उपयोग करते हैं। क्लाइंट कोड के बजाय विधि नामों के लिए कठिन युग्मित किया जाएगा। देखो कि कितने पुस्तकालयों में "अपवित्र" टैग / एनोटेशन के साथ पुराने तरीकों को शामिल करना है क्योंकि पुराने कोड अभी भी उन पर निर्भर हैं (और कुछ लोग अभी भी उनका उपयोग कर सकते हैं क्योंकि उन्हें उनके साथ काम करना आसान लगता है, लेकिन आप नहीं हैं ऐसा करने वाला है)।
JAB

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

3
@ user949300 मुझे बताएं कि मैं किन लोगों को सीख सकता हूं।
ट्यूलेंस कोरडोवा

6

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

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