समय की महत्वपूर्ण राशि, मैं एक स्थिर वर्ग के बजाय एक वस्तु होने का कारण नहीं सोच सकता। क्या मेरे विचार से वस्तुओं के अधिक लाभ हैं? [बन्द है]


9

मैं एक वस्तु की अवधारणा को समझता हूं, और एक जावा प्रोग्रामर के रूप में मुझे लगता है कि ओओ प्रतिमान स्वाभाविक रूप से मेरे व्यवहार में आता है।

हालाँकि हाल ही में मैंने खुद को यह सोचते हुए पाया:

एक सेकंड रुको, वास्तव में एक स्थिर वर्ग (उचित एनकैप्सुलेशन और OO प्रथाओं के साथ) का उपयोग करके किसी वस्तु का उपयोग करने के व्यावहारिक लाभ क्या हैं?

मैं एक वस्तु के उपयोग के दो लाभों के बारे में सोच सकता था (दोनों महत्वपूर्ण और शक्तिशाली हैं):

  1. बहुरूपता: आपको रनटाइम के दौरान कार्यक्षमता को गतिशील और लचीले ढंग से स्वैप करने की अनुमति देता है। साथ ही आसानी से सिस्टम में नई कार्यक्षमता 'पार्ट्स' और विकल्प जोड़ने की अनुमति देता है। उदाहरण के लिए यदि वस्तुओं के Carसाथ काम करने के लिए डिज़ाइन किया गया एक वर्ग है Engine, और आप उस सिस्टम में एक नया इंजन जोड़ना चाहते हैं जिसे कार उपयोग कर सकती है, तो आप एक नया Engineउपवर्ग बना सकते हैं और बस इस वर्ग के Carऑब्जेक्ट को ऑब्जेक्ट में डाल सकते हैं , बिना के बारे में कुछ भी बदलने Car। और आप रनटाइम के दौरान ऐसा करने का फैसला कर सकते हैं।

  2. 'कार्यक्षमता पास करने में सक्षम' होने के कारण: आप सिस्टम के चारों ओर गतिशील रूप से एक ऑब्जेक्ट पास कर सकते हैं।

लेकिन क्या स्थैतिक वर्गों से अधिक वस्तुओं के लिए कोई और फायदे हैं?

अक्सर जब मैं एक सिस्टम में नए 'भागों' को जोड़ता हूं, तो मैं एक नया वर्ग बनाकर और उससे तात्कालिक वस्तुओं को जोड़कर ऐसा करता हूं।

लेकिन हाल ही में जब मैंने रोका और इसके बारे में सोचा, तो मुझे एहसास हुआ कि एक स्थिर वर्ग एक ऑब्जेक्ट के समान ही करेगा, बहुत सारे स्थानों पर जहां मैं सामान्य रूप से किसी ऑब्जेक्ट का उपयोग करता हूं।

उदाहरण के लिए, मैं अपने ऐप में सेव / लोड-फाइल तंत्र जोड़ने पर काम कर रहा हूं।

किसी ऑब्जेक्ट के साथ, कोड की कॉलिंग लाइन इस तरह दिखाई देगी: Thing thing = fileLoader.load(file);

एक स्थिर वर्ग के साथ, यह इस तरह दिखेगा: Thing thing = FileLoader.load(file);

क्या फर्क पड़ता है?

बहुत बार मैं सिर्फ एक वस्तु को तत्काल करने का एक कारण नहीं सोच सकता जब एक सादे-पुराने स्थैतिक-वर्ग बस एक ही कार्य करेंगे। लेकिन OO प्रणालियों में, स्थिर वर्ग काफी दुर्लभ हैं। इसलिए मुझे कुछ याद आ रहा है।

क्या मेरे द्वारा सूचीबद्ध दो से अन्य वस्तुओं के लिए कोई और अधिक लाभ हैं? कृपया समझाएँ।

संपादित करें: स्पष्ट करने के लिए। कार्यक्षमता को अदला-बदली करते समय, या डेटा पास करते समय मुझे बहुत उपयोगी चीज़ें मिलती हैं। उदाहरण के लिए मैंने एक ऐप लिखा है जो धुन बनाता है। MelodyGeneratorकई उपवर्ग थे, जो अलग-अलग तरह से धुन बनाते थे, और इन वर्गों की वस्तुएँ विनिमेय (रणनीति पैटर्न) थीं।

धुनें भी वस्तुएं थीं, क्योंकि उनके चारों ओर से गुजरना उपयोगी है। तो जीवा और तराजू थे।

लेकिन सिस्टम के 'स्टैटिक' हिस्सों के बारे में क्या - जो कि पास होने वाला नहीं है? उदाहरण के लिए - एक 'फ़ाइल सहेजें' तंत्र। मुझे इसे एक वस्तु में क्यों लागू करना चाहिए, न कि एक स्थिर वर्ग में?


इसलिए, खेतों और शायद विधियों के साथ एक वस्तु के बजाय, कोई वस्तु, कोई रिकॉर्ड नहीं, बस एक बहुत सारे स्केलर मान पारित किए गए और स्थिर तरीकों से वापस आ गए? संपादित करें: आपका नया उदाहरण अन्यथा सुझाव देता है: वस्तुएं, उदाहरण के तरीकों के बिना? नहीं तो क्या है Thing?

क्या होता है जब आपको FileLoaderएक सॉकेट से पढ़ने वाले के लिए स्वैप करने की आवश्यकता होती है ? या परीक्षण के लिए एक नकली? या एक जो ज़िप फ़ाइल खोलता है?
बेंजामिन हॉजसन


1
@delnan ठीक है मुझे एक सवाल लगा कि जवाब मुझे समझने में मदद करेगा: आप एक वस्तु के रूप में सिस्टम के 'स्थिर' भाग को क्यों लागू करेंगे? प्रश्न में उदाहरण की तरह: एक सेव-फाइल तंत्र। किसी वस्तु में इसे लागू करने से मुझे क्या लाभ होगा?
अवीव कोहन

1
डिफ़ॉल्ट को एक गैर-स्थिर ऑब्जेक्ट का उपयोग करना चाहिए। केवल स्थिर वर्गों का उपयोग करें यदि आपको लगता है कि यह वास्तव में आपके इरादे को बेहतर ढंग से व्यक्त करता है। System.Math.NET में एक ऐसी चीज का एक उदाहरण है जो एक स्थिर वर्ग के रूप में बहुत अधिक समझ में आता है: आपको इसे स्वैप करने या इसे नकली करने की आवश्यकता नहीं है और संचालन में से कोई भी तार्किक रूप से एक उदाहरण का हिस्सा नहीं बन सकता है। मुझे नहीं लगता कि आपका 'बचत' उदाहरण उस बिल पर फिट बैठता है।
बेंजामिन हॉजसन

जवाबों:


14

lol आप एक टीम की तरह आवाज करते हैं जिसे मैं काम करता था;)

जावा (और शायद C #) निश्चित रूप से उस प्रोग्रामिंग शैली का समर्थन करता है। और मैं उन लोगों के साथ काम करता हूं जो पहली वृत्ति है, "मैं इसे एक स्थिर विधि बना सकता हूं!" लेकिन कुछ सूक्ष्म लागतें हैं जो समय के साथ आपके साथ बढ़ती हैं।

1) जावा एक ऑब्जेक्ट ओरिएंटेड भाषा है। और यह कार्यात्मक लोगों को पागल करता है, लेकिन वास्तव में यह बहुत अच्छा है। OO के पीछे का विचार राज्य के साथ कार्यक्षमता को छोटा करने के लिए है जिसमें डेटा और कार्यक्षमता की छोटी इकाइयाँ होती हैं जो राज्य को छिपाकर और उस संदर्भ में समझ में आने वाले कार्यों को उजागर करके उनके शब्दार्थ को संरक्षित करती हैं।

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

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

2) OO के नियम बहुत अच्छी तरह से समझे गए हैं। थोड़ी देर के बाद, आप एक वर्ग डिजाइन को देख सकते हैं और देख सकते हैं कि क्या यह एसओएलआईडी जैसे मानदंडों को पूरा करता है। और बहुत सारे अभ्यास इकाई परीक्षण के बाद, आप एक अच्छी समझ विकसित करते हैं जो एक वर्ग को "सही आकार" और "सुसंगत" बनाता है। लेकिन सभी स्थिर तरीकों के साथ एक वर्ग के लिए अच्छे नियम नहीं हैं, और कोई वास्तविक कारण नहीं है कि आपको वहां सब कुछ बंडल नहीं करना चाहिए। आपके संपादक में वर्ग खुला है, तो क्या बिल्ली? बस वहाँ अपनी नई विधि जोड़ें। थोड़ी देर के बाद, आपका आवेदन "गॉड ऑब्जेक्ट्स" प्रतिस्पर्धा में बदल जाता है, प्रत्येक दुनिया पर हावी होने की कोशिश कर रहा है। फिर, उन्हें छोटी इकाइयों में फिर से लाना अत्यधिक व्यक्तिपरक है और यह बताना मुश्किल है कि क्या आपने इसे सही पाया है।

3) इंटरफेस जावा की सबसे शक्तिशाली विशेषताओं में से एक हैं। क्लास इनहेरिटेंस समस्याग्रस्त साबित हुई है, लेकिन इंटरफेस के साथ प्रोग्रामिंग भाषा की सबसे शक्तिशाली चाल में से एक बनी हुई है। (ditto C #) सभी-स्थिर वर्ग खुद को उस मॉडल में नहीं डाल सकते।

4) यह महत्वपूर्ण OO तकनीकों पर दरवाजा खींचता है जिनका आप लाभ नहीं उठा सकते हैं। तो आप अपने टूलबॉक्स में केवल एक हथौड़ा के साथ वर्षों तक काम कर सकते हैं, बिना यह महसूस किए कि कितनी आसान चीजें होती अगर आप एक पेचकश भी होते।

४.५) यह सबसे कठिन, अटूट संकलन-समय पर निर्भरता को संभव बनाता है। इसलिए, उदाहरण के लिए, यदि आपके पास है FileSystem.saveFile()तो बदलने का कोई तरीका नहीं है, जो आपके जेवीएम को रन टाइम के दौरान बंद कर देता है। जिसका अर्थ है कि आपके स्टैटिक फंक्शन क्लास को संदर्भित करने वाला हर वर्ग उस विशिष्ट कार्यान्वयन पर एक कठिन, संकलन-समय पर निर्भरता रखता है, जो विस्तार को लगभग असंभव बना देता है, और परीक्षण को जबरदस्त रूप से जटिल बना देता है। आप अलगाव में स्थिर वर्ग का परीक्षण कर सकते हैं, लेकिन उन कक्षाओं का परीक्षण करना बहुत मुश्किल हो जाता है जो उस वर्ग को अलगाव में संदर्भित करते हैं।

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

जब मैं किसी भाषा में होता हूं, तो मैं हमेशा अच्छी भाषा का उपयोग करने की कोशिश करता हूं। इसलिए, उदाहरण के लिए, जब मैं जावा में हूं, तो मैं अच्छे ओओ डिजाइन का उपयोग करता हूं, क्योंकि तब मैं वास्तव में भाषा का लाभ उठाता हूं कि यह क्या करता है। जब मैं पायथन में होता हूं, तो मैं कभी-कभार कक्षाओं के साथ मॉड्यूल-स्तर के कार्यों को मिलाता हूं - मैं केवल पायथन में कक्षाएं लिख सकता हूं, लेकिन फिर मुझे लगता है कि मैं भाषा का उपयोग नहीं करूंगा जो इसमें अच्छा है।

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

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

यह एक कठिन है, हालांकि। मैंने देखा है कि लोगों को "सभी स्थिर" बग मिलते हैं, और उन्हें इससे बाहर बात करना कठिन है। लेकिन मैंने देखा है कि जब वे इस पर पहुंचते हैं तो उन्हें राहत की बड़ी अनुभूति होती है।


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

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

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

3
"ओओ के पीछे का विचार राज्य के साथ कार्यक्षमता को बंडल कर रहा है जिसमें डेटा और कार्यक्षमता की छोटी इकाइयां हैं जो राज्य को छिपाकर और उस संदर्भ में समझ में आने वाले कार्यों को उजागर करके अपने शब्दार्थ को संरक्षित करते हैं।" यह मौलिक रूप से गलत है। OO परस्पर परिवर्तनशील नहीं है और अमूर्तता OO के लिए अनन्य नहीं है। अमूर्तता प्राप्त करने के दो तरीके हैं और वस्तुएं उनमें से केवल एक हैं (दूसरा सार डेटा प्रकार)।
डोभाल

1
@ डोवल मुझे समझ में नहीं आता कि क्यों ओओ की हर चर्चा को कार्यात्मक प्रोग्रामिंग की चर्चा में बदलना चाहिए।
रोब

6

तुम ने पूछा था:

लेकिन क्या स्थैतिक वर्गों से अधिक वस्तुओं के लिए कोई और फायदे हैं?

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

हालांकि, वे लाभ नहीं हैं। लाभ हैं:

  1. बेहतर अमूर्तता
  2. बेहतर रखरखाव
  3. बेहतर परीक्षणशीलता

तुमने कहा था:

लेकिन हाल ही में जब मैंने रोका और इसके बारे में सोचा, तो मुझे एहसास हुआ कि एक स्थिर वर्ग एक ऑब्जेक्ट के समान ही करेगा, बहुत सारे स्थानों पर जहां मैं सामान्य रूप से किसी ऑब्जेक्ट का उपयोग करता हूं।

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

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

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

तुम ने पूछा था:

किसी ऑब्जेक्ट के साथ, कोड की कॉलिंग लाइन इस तरह दिखाई देगी: Thing thing = fileLoader.load(file);

एक स्थिर वर्ग के साथ, यह इस तरह दिखेगा: Thing thing = FileLoader.load(file);

क्या फर्क पड़ता है?

यदि कभी भी , किसी भी डेटा को स्टोर करने की आवश्यकता FileLoaderनहीं है, तो मैं दूसरे दृष्टिकोण के साथ जाऊंगा। अगर एक मौका है कि यह ऑपरेशन करने के लिए सहायक डेटा की आवश्यकता होगी, तो एक पहला स्मीजेन होता है, पहला दृष्टिकोण एक सुरक्षित शर्त है।

तुम ने पूछा था:

क्या मेरे द्वारा सूचीबद्ध दो से अन्य वस्तुओं के लिए कोई और अधिक लाभ हैं? कृपया समझाएँ।

मैंने OO प्रतिमान के उपयोग के लाभों (फायदे) को सूचीबद्ध किया। मुझे आशा है कि वे स्वयं व्याख्यात्मक हैं। यदि नहीं, तो मुझे खुशी होगी।

तुम ने पूछा था:

लेकिन सिस्टम के 'स्टैटिक' हिस्सों के बारे में क्या - जो कि पास होने वाला नहीं है? उदाहरण के लिए - एक 'फ़ाइल सहेजें' तंत्र। मुझे इसे एक वस्तु में क्यों लागू करना चाहिए, न कि एक स्थिर वर्ग में?

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

  1. इसे CSV फ़ाइल में सहेजें।
  2. इसे XML फाइल में सेव करें।
  3. इसे एक json फ़ाइल में सहेजें।
  4. इसे बाइनरी फ़ाइल के रूप में सहेजें, डेटा के प्रत्यक्ष डंप के साथ।
  5. इसे किसी डेटाबेस में सीधे किसी तालिका में सहेजें।

इस तरह के विकल्प प्रदान करने का एकमात्र तरीका एक इंटरफ़ेस बनाना है और इंटरफ़ेस को लागू करने वाली वस्तुओं का निर्माण करना है।

निष्कर्ष के तौर पर

हाथ में समस्या के लिए सही दृष्टिकोण का उपयोग करें। एक दृष्टिकोण बनाम दूसरे के बारे में धार्मिक न होना बेहतर है।


इसके अलावा, अगर कई अलग अलग वस्तु प्रकार (वर्ग) की जरूरत है बचाया जा (जैसे Melody, Chord, Improvisations, SoundSampleऔर अन्य), तो यह कपोल-कल्पना के माध्यम से कार्यान्वयन को आसान बनाने के किफायती हो जाएगा।
रौंग

5

यह कभी-कभी भाषा और संदर्भ पर निर्भर करता है। उदाहरण के लिए, PHPसर्विसिंग अनुरोधों के लिए उपयोग की जाने वाली स्क्रिप्ट में हमेशा सेवा के लिए एक अनुरोध और स्क्रिप्ट के पूरे जीवनकाल में एक प्रतिक्रिया उत्पन्न होती है, इसलिए अनुरोध पर कार्य करने और प्रतिक्रिया उत्पन्न करने के लिए स्थिर तरीके उपयुक्त हो सकते हैं। लेकिन एक सर्वर पर लिखा है Node.js, एक ही समय में कई अलग-अलग अनुरोध और प्रतिक्रियाएं हो सकती हैं। तो पहला सवाल यह है - क्या आप सुनिश्चित हैं कि स्थिर वर्ग वास्तव में एक सिंगलटन ऑब्जेक्ट से मेल खाता है?

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

आपने ऊपर दिए गए फ़ायदों का उल्लेख किया है, इसलिए यहाँ एक है: आपने विरासत में नहीं दिया है। कई भाषाओं में स्थिर तरीकों को ओवरराइड करने की कोई क्षमता नहीं है, उदाहरण के तरीकों को ओवरराइड किया जा सकता है। सामान्य तौर पर, स्थैतिक विधियों को विरासत में लेना और ओवरराइड करना बहुत कठिन होता है।


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

3

रोब वाई के पद के अलावा


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

हालाँकि, जैसे ही इनमें से दो कार्य एक सामान्य उपयोग के लिए शुरू होते हैं, जिन्हें आप किसी भी तरह से समूह बनाना चाहते हैं। कल्पना करें कि आपके पास न केवल एक loadफ़ंक्शन है, बल्कि एक hasValidSyntaxफ़ंक्शन भी है । आप क्या करेंगे?

     if (FileLoader.hasValidSyntax(myfile))
          Thing thing = FileLoader.load(myfile);
     else
          println "oh noes!"

myfileयहाँ दो संदर्भ देखें ? आप अपने आप को दोहराना शुरू करते हैं क्योंकि आपके बाहरी राज्य को हर कॉल के लिए पारित करना पड़ता है। रोब वाई ने बताया है कि आप किस तरह से राज्य को (यहाँ file) आंतरिक करते हैं ताकि आप इसे इस तरह से कर सकें:

     FileLoader myfileLoader = new FileLoader(myfile)
     if (myfileLoader.hasValidSyntax())
          Thing thing = myfileLoader.load();
     else
          println "oh noes!"

एक ही वस्तु में दो बार पास होना एक सतही लक्षण है; वास्तविक समस्या यह इंगित कर सकती है कि कुछ कार्य अतिरेक से किए जाते हैं - फ़ाइल को दो बार खोलना पड़ सकता है, दो बार पार्स किया जा सकता है, और दो बार बंद किया जा सकता है, यदि hasValidSyntax()और load()उन्हें राज्य का पुन: उपयोग करने की अनुमति नहीं है (आंशिक रूप से पार्स फ़ाइल का परिणाम)।
रौंग

2

स्थिर कक्षाओं का उपयोग करते समय एक प्रमुख मुद्दा यह है कि वे आपको अपनी निर्भरता को छिपाने के लिए मजबूर करते हैं, और आपको कार्यान्वयन पर निर्भर करने के लिए मजबूर करते हैं। निम्नलिखित कंस्ट्रक्टर हस्ताक्षर में, आपकी निर्भरताएं क्या हैं:

public Person(String name)

खैर, हस्ताक्षर से देखते हुए, एक व्यक्ति को सिर्फ एक नाम की आवश्यकता है, है ना? ठीक है, नहीं तो कार्यान्वयन है:

public Person(String name) {
    ResultSet rs = DBConnection.getPersonFilePathByName(name);
    File f = FileLoader.load(rs.getPath());
    PersonData.setDataFile(f);
    this.name = name;
    this.age = PersonData.getAge();
}

तो एक व्यक्ति सिर्फ तात्कालिक नहीं है। हम वास्तव में एक डेटाबेस से डेटा खींचते हैं, जो हमें एक फ़ाइल का मार्ग देता है, जिसे तब पार्स किया जाना चाहिए, और फिर जो वास्तविक डेटा हम चाहते हैं उसे छेड़ा जाना चाहिए। यह उदाहरण स्पष्ट रूप से शीर्ष पर है, लेकिन यह बात साबित करता है। लेकिन रुकिए, और भी बहुत कुछ हो सकता है! मैं निम्नलिखित परीक्षण लिखता हूं:

public void testPersonConstructor() {
    Person p = new Person("Milhouse van Houten");
    assertEqual(10, p.age);
}

यह हालांकि, सही पास होना चाहिए? मेरा मतलब है, हमने उस सभी सामान को सही तरीके से समझाया? खैर, वास्तव में यह एक अपवाद के साथ चल रहा है। क्यों? ओह, हाँ, छिपी हुई निर्भरताएँ जिनके बारे में हमें नहीं पता था कि वैश्विक स्थिति है। DBConnectionजरूरतों को प्रारंभ और जुड़ा हुआ है। FileLoaderकिसी FileFormatवस्तु (जैसे XMLFileFormatया CSVFileFormat) से आरंभ की गई जरूरतें । उन लोगों के बारे में कभी नहीं सुना? खैर, यह बात है। आपका कोड (और आपका संकलक) आपको यह नहीं बता सकता है कि आपको इन चीजों की आवश्यकता है क्योंकि स्थिर कॉल उन निर्भरता को छिपाते हैं। क्या मैंने परीक्षण कहा? मेरा मतलब था कि नए जूनियर डेवलपर ने आपकी सबसे हालिया रिलीज में कुछ इस तरह से भेज दिया। आखिरकार, संकलित = काम करता है, है ना?

इसके अतिरिक्त, मान लें कि आपके पास एक ऐसी प्रणाली है जिसमें MySQL इंस्टेंस नहीं चल रहा है। या, कहें कि आप एक विंडोज सिस्टम पर हैं, लेकिन आपकी DBConnectionकक्षा केवल लिनक्स बॉक्स (लिनक्स पथों के साथ) पर आपके MySQL सर्वर पर जाती है। या, यह कहें कि आप एक ऐसी प्रणाली पर हैं जहाँ आपके द्वारा दिया गया पथ DBConnectionआपके लिए पढ़ा / लिखा नहीं है। इसका मतलब है कि इनमें से किसी भी परिस्थिति में इस प्रणाली को चलाने या परीक्षण करने की कोशिश विफल रहेगी, कोड त्रुटि के कारण नहीं, बल्कि एक डिज़ाइन त्रुटि के कारण जो कोड के लचीलेपन को सीमित करती है और आपको क्रियान्वयन तक सीमित करती है।

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

क्या यह हमेशा बुरा होता है? ज़रूरी नहीं, लेकिन अपनी बात को उल्टा करना बेहतर हो सकता है और कहें कि "क्या एक अच्छा कारण है कि यह उदाहरण नहीं होना चाहिए ?" बजाय "वहाँ एक अच्छा कारण है यह एक उदाहरण होना चाहिए ?" यदि आप वास्तव में कह सकते हैं कि आपका कोड अटूट (और स्टेटलेस) होगा Math.abs(), जैसा कि इसके कार्यान्वयन में और इसके उपयोग के तरीके दोनों में है, तो आप इसे स्थिर बनाने पर विचार कर सकते हैं। हालांकि, स्थैतिक वर्गों पर उदाहरण होने से, आपको लचीलेपन की एक ऐसी दुनिया मिलती है, जो इस तथ्य के बाद हमेशा आसान नहीं होती है। यह आपको आपके कोड की निर्भरता की वास्तविक प्रकृति में और अधिक स्पष्टता प्रदान कर सकता है।


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

लेकिन छिपी निर्भरताएं गैर-स्थिर वर्ग में भी मौजूद हो सकती हैं? इसलिए मैं यह नहीं देखता कि यह स्टैटिक क्लास की खामी क्यों होगी, लेकिन नॉन-स्टैटिक क्लास की नहीं।
वैलेंट्री

@valenterry हाँ, हम गैर-स्थिर निर्भरताओं को भी छिपा सकते हैं, लेकिन मुख्य बिंदु यह है कि गैर-स्थिर निर्भरताओं को छुपाना एक विकल्प है । मैं newकंस्ट्रक्टर में वस्तुओं का एक गुच्छा उठा सकता हूं (जो आमतौर पर उचित नहीं है), लेकिन मैं उन्हें इंजेक्ट भी कर सकता हूं। स्थिर कक्षाओं के साथ, उन्हें इंजेक्ट करने का कोई तरीका नहीं है (वैसे भी जावा में आसानी से नहीं, और यह उन भाषाओं के लिए एक पूरी अन्य चर्चा होगी जो इसकी अनुमति देती हैं), इसलिए कोई विकल्प नहीं है। इसलिए मैं अपने उत्तर में बहुत अधिक निर्भरता छिपाने में मजबूर होने के विचार को उजागर करता हूं।
cbojar

लेकिन आप हर बार जब आप विधि को कॉल करते हैं, तो उन्हें तर्क प्रदान करके इंजेक्ट कर सकते हैं । इसलिए आप उन्हें छिपाने के लिए मजबूर नहीं हैं, लेकिन उन्हें स्पष्ट करने के लिए मजबूर किया जाता है ताकि हर कोई "अहा, विधि इन तर्कों पर निर्भर करता है" के बजाय "अहा, उस विधि पर निर्भर करता है" इन (तर्कों का हिस्सा) और कुछ छिपे हुए अंतर राज्य मैं नहीं। जानना"।
वैलेंट्री

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

1

केवल मेरे दो सेंट्स।

आपके प्रश्न के लिए:

लेकिन सिस्टम के 'स्टैटिक' हिस्सों के बारे में क्या - जो कि पास होने वाला नहीं है? उदाहरण के लिए - एक 'फ़ाइल सहेजें' तंत्र। मुझे इसे एक वस्तु में क्यों लागू करना चाहिए, न कि एक स्थिर वर्ग में?

आप अपने आप से पूछ सकते हैं कि सिस्टम के भाग का तंत्र ध्वनियों को बजाता है, या सिस्टम का वह भाग जो किसी फ़ाइल WANGE श्रेणी में डेटा बचाता है । यदि आपका उत्तर हां है, तो यह इंगित करता है कि आपको उनका उपयोग करके सार करना चाहिए abstract class/ interface। आप पूछ सकते हैं, मैं भविष्य की चीजों को कैसे जान सकता हूं? निश्चित रूप से, हम नहीं कर सकते। इसलिए, अगर बात स्टेटलेस है, तो आप 'स्टैटिक क्लास' का उपयोग कर सकते हैं java.lang.Math, जैसे , अन्यथा, ऑब्जेक्ट-ओरिएंटेड दृष्टिकोण का उपयोग करें।


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