एक वर्ग को "अमूर्त" या "अंतिम / सील" के अलावा और कुछ क्यों होना चाहिए?


29

जावा / सी # प्रोग्रामिंग के 10+ वर्षों के बाद, मैं खुद को या तो बना पाया:

  • अमूर्त वर्ग : अनुबंध का तात्पर्य यह नहीं है कि जैसा है वैसा किया जाए।
  • अंतिम / सीलबंद वर्ग : कार्यान्वयन का अर्थ आधार वर्ग के रूप में किसी और चीज की सेवा करना नहीं है।

मैं किसी भी स्थिति के बारे में नहीं सोच सकता, जहां एक साधारण "क्लास" (यानी न तो सार और न ही अंतिम / सील) "बुद्धिमान प्रोग्रामिंग" होगी।

एक वर्ग को "अमूर्त" या "अंतिम / सील" के अलावा और कुछ क्यों होना चाहिए?

संपादित करें

यह महान लेख मेरी चिंताओं को मुझसे बेहतर बताता है।


21
क्योंकि यह कहा जाता है Open/Closed principle, नहींClosed Principle.
StuperUser

2
आप पेशेवर किस प्रकार की चीजें लिख रहे हैं? यह मामले पर आपकी राय को बहुत अच्छी तरह से प्रभावित कर सकता है।

खैर, मुझे पता है कि कुछ प्लेटफ़ॉर्म देवता हैं जो सब कुछ सील कर देते हैं, क्योंकि वे वंशानुक्रम इंटरफ़ेस को कम से कम करना चाहते हैं।
के ..

4
@StuperUser: यह एक कारण नहीं है, यह एक पठार है। ओपी यह नहीं पूछ रहा है कि पठार क्या है, वह पूछ रहा है कि क्यों । यदि किसी सिद्धांत के पीछे कोई कारण नहीं है, तो उस पर ध्यान देने का कोई कारण नहीं है।
माइकल शॉ

1
मुझे आश्चर्य है कि विंडो क्लास को सील में बदलने से कितने यूआई फ्रेमवर्क टूट जाएंगे।
रिएक्टगुलर

जवाबों:


46

विडंबना यह है कि मैं इसके विपरीत पाता हूं: अमूर्त वर्गों का उपयोग नियम के बजाय अपवाद है और मैं अंतिम या सील किए गए वर्गों पर ध्यान केंद्रित करता हूं।

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

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

इस बाद के दृश्य को 3 पार्टी घटकों के साथ काम करके मेरे लिए सीमेंट किया गया है जो कि वर्गों को सील कर देता है जिससे कुछ एकीकरण को रोका जा सकता है जिससे जीवन बहुत आसान हो जाता है।


17
अंतिम पैराग्राफ के लिए +1। मैंने अक्सर 3 पार्टी लाइब्रेरी (या मानक पुस्तकालय कक्षाएं!) में बहुत अधिक इनकैप्सुलेशन पाया है जो बहुत कम एनकैप्सुलेशन की तुलना में दर्द का एक बड़ा कारण है।
मेसन व्हीलर

5
सीलिंग कक्षाओं के लिए सामान्य तर्क यह है कि आप कई अलग-अलग तरीकों का अनुमान नहीं लगा सकते हैं कि एक ग्राहक संभवतः आपकी कक्षा को ओवरराइड कर सकता है, और इसलिए आप इसके व्यवहार के बारे में कोई गारंटी नहीं दे सकते। देखें ब्लॉगs.msdn.com/b/ericlippert/archive/2004/01/22/…
रॉबर्ट हार्वे

12
@ रोबर्टहवे मैं तर्क से परिचित हूं और यह सिद्धांत में बहुत अच्छा लगता है। ऑब्जेक्ट डिजाइनर के रूप में आप यह नहीं भूल सकते कि लोग आपकी कक्षाओं का विस्तार कैसे कर सकते हैं - यही कारण है कि उन्हें सील नहीं किया जाना चाहिए । आप सब कुछ ठीक नहीं कर सकते। मत करो। लेकिन विकल्पों को दूर न करें, या तो।
माइकल

6
@RobertHarvey यह नहीं है कि सिर्फ एलएसपी को तोड़ने वाले लोगों को वह मिल रहा है जिसके वे हकदार हैं?
स्टुपरयूज़र

2
मैं सीलबंद कक्षाओं का बहुत बड़ा प्रशंसक नहीं हूं, लेकिन मैं यह देख सकता था कि क्यों माइक्रोसॉफ्ट जैसी कुछ कंपनियां (जिन्हें अक्सर उन चीजों का समर्थन करना पड़ता है जो वे खुद नहीं तोड़ती थीं) उन्हें आकर्षक लगती हैं। किसी फ्रेमवर्क के उपयोगकर्ताओं को जरूरी नहीं है कि उन्हें कक्षा के इंटर्नल का ज्ञान हो।
रॉबर्ट हार्वे

11

यही कारण है कि है एरिक Lippert द्वारा एक महान लेख, लेकिन मैं इसे अपने दृष्टिकोण का समर्थन करता है नहीं लगता।

उनका तर्क है कि दूसरों द्वारा उपयोग के लिए उजागर सभी वर्गों को सील कर दिया जाना चाहिए, या अन्यथा गैर-एक्स्टेंसिबल बना दिया जाना चाहिए।

आपका आधार यह है कि सभी कक्षाएं सार या सील होनी चाहिए।

बड़ा अंतर।

ईएल का लेख कहता है कि उनकी टीम द्वारा निर्मित (संभवतः कई) कक्षाओं के बारे में कुछ भी नहीं है जिसके बारे में आप और मैं कुछ भी नहीं जानते हैं। सामान्य रूप से किसी ढांचे में सार्वजनिक रूप से उजागर होने वाली कक्षाएं केवल उस ढांचे को लागू करने में शामिल सभी वर्गों का एक सबसेट होती हैं।


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

मुझे लगता है कि कक्षाएं अमूर्त या सील होनी चाहिए, यह एक व्यापक सिद्धांत का हिस्सा है, जो यह है कि व्यक्ति को तत्काल श्रेणी प्रकारों के चर का उपयोग करने से बचना चाहिए। इस तरह के परिहार से एक प्रकार का निर्माण करना संभव हो जाएगा, जिसे किसी भी प्रकार के उपभोक्ताओं द्वारा उपयोग किया जा सकता है, इसके बिना सभी निजी सदस्यों को विरासत में प्राप्त करना होगा। दुर्भाग्य से, इस तरह के डिजाइन वास्तव में सार्वजनिक-निर्माण सिंटैक्स के साथ काम नहीं करते हैं। इसके बजाय, कोड को new List<Foo>()कुछ के साथ बदलना होगा List<Foo>.CreateMutable()
सुपरकाट

5

एक जावा परिप्रेक्ष्य से मुझे लगता है कि अंतिम वर्ग उतने स्मार्ट नहीं हैं जितना कि लगता है।

कई उपकरण (विशेष रूप से एओपी, जेपीए आदि) लोड टाइम वेविंग के साथ काम करते हैं ताकि उन्हें आपके क्लैस का विस्तार करना पड़े। दूसरा तरीका डेलिगेट्स बनाना होगा (नेट वाले नहीं) सब कुछ ओरिजिनल क्लास को सौंपते हैं, जो यूजर्स क्लासेस को बढ़ाने से ज्यादा गन्दा होगा।


5

दो सामान्य मामले जहां आपको वनीला, गैर-सील वर्गों की आवश्यकता होगी :

  1. तकनीकी: यदि आपके पास एक पदानुक्रम है जो दो स्तरों से अधिक गहरा है , और आप बीच में कुछ पल करना चाहते हैं।

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

सीलिंग पर एरिक लिपर्ट के विचार समझ में आते हैं, लेकिन वह यह भी स्वीकार करते हैं कि वे कक्षा को "खुला" छोड़कर विलुप्ति के लिए डिजाइन करते हैं

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

दो .NET विशिष्ट नोट:

  1. ज्यादातर परिस्थितियों में, सीलिंग कक्षाएं अक्सर सुरक्षा के लिए महत्वपूर्ण नहीं होती हैं, क्योंकि virtualस्पष्ट इंटरफ़ेस कार्यान्वयन के अपवाद के साथ उत्तराधिकारी आपकी गैर- कार्यक्षमता के साथ खिलवाड़ नहीं कर सकते हैं ।
  2. कभी-कभी internalकक्षा को सील करने के बजाय कंस्ट्रक्टर बनाने के लिए एक उपयुक्त विकल्प होता है , जो इसे आपके कोडबेस के अंदर विरासत में प्राप्त करने की अनुमति देता है, लेकिन इसके बाहर नहीं।

4

मेरा मानना ​​है कि वास्तविक कारण कई लोगों को लगता है कि कक्षाएं होनी चाहिए final/ sealedयह है कि अधिकांश गैर-अमूर्त विस्तार योग्य कक्षाएं ठीक से प्रलेखित नहीं हैं ।

मुझे विस्तार से बताएं दूर से शुरू होने पर, कुछ प्रोग्रामर्स के बीच यह विचार है कि ओओपी में एक उपकरण के रूप में विरासत का व्यापक रूप से दुरुपयोग और दुरुपयोग किया जाता है। हम सभी ने लिस्कोव प्रतिस्थापन सिद्धांत पढ़ा है, हालांकि यह हमें सैकड़ों (शायद हजारों भी) का उल्लंघन करने से रोक नहीं पाया।

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

एक अंतिम / सील वर्ग के लिए उचित प्रलेखन अपेक्षाकृत छोटा है: आप वर्णन करते हैं कि प्रत्येक विधि क्या करती है, तर्क क्या हैं, वापसी मूल्य, आदि सभी सामान्य सामान।

हालाँकि, जब आप एक विस्तार योग्य वर्ग का सही ढंग से दस्तावेजीकरण कर रहे हैं, तो आपको कम से कम निम्नलिखित को शामिल करना होगा :

  • तरीकों के बीच निर्भरता (कौन सी विधि किसको कॉल करती है, आदि)
  • स्थानीय चर पर निर्भरता
  • आंतरिक अनुबंध जो विस्तारित वर्ग का सम्मान करना चाहिए
  • प्रत्येक विधि के लिए कॉल कन्वेंशन (जैसे जब आप इसे ओवरराइड करते हैं, तो क्या आप superकार्यान्वयन को कॉल करते हैं? क्या आप इसे विधि की शुरुआत में कहते हैं, या अंत में? कंस्ट्रक्टर बनाम विध्वंसक सोचो)
  • ...

ये मेरे सिर के ठीक ऊपर हैं। और मैं आपको इस बात का एक उदाहरण प्रदान कर सकता हूं कि इनमें से प्रत्येक क्यों महत्वपूर्ण है और इसे लंघन करने से एक विस्तारित वर्ग खराब हो जाएगा।

अब, विचार करें कि इनमें से प्रत्येक चीज़ का दस्तावेजीकरण करने के लिए दस्तावेज़ीकरण प्रयास कितना सही होना चाहिए। मेरा मानना ​​है कि 7-8 तरीकों वाला एक वर्ग (जो एक आदर्श दुनिया में बहुत अधिक हो सकता है, लेकिन वास्तविक में बहुत कम है) साथ ही 5 पृष्ठों के बारे में एक दस्तावेज हो सकता है, केवल-पाठ। इसलिए, इसके बजाय, हम आधे रास्ते से बाहर निकल गए और कक्षा को सील नहीं किया, ताकि अन्य लोग इसका उपयोग कर सकें, लेकिन इसे ठीक से दस्तावेज न करें, क्योंकि यह एक विशाल राशि लेगा (और, आप जानते हैं, यह हो सकता है वैसे भी कभी नहीं बढ़ाया जाना चाहिए, तो क्यों परेशान?)।

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

मुझे लगता है कि एक समाधान के कुछ तत्व हैं:

  • यह सुनिश्चित करने के लिए कि कोड के ग्राहक होने पर, और वास्तव में वंशानुक्रम पर रचना का पक्ष लेना एक अच्छा विचार है
  • दूसरा यह सुनिश्चित करने के लिए कि यह उल्लेख किया गया है कि आप कुछ अनदेखी नहीं कर रहे हैं, यह सुनिश्चित करने के लिए मैनुअल को पूरी तरह से (फिर से एक ग्राहक के रूप में) पढ़ने के लिए
  • तीसरा, जब आप कोड का एक टुकड़ा लिख ​​रहे हों, जिसका उपयोग ग्राहक करेगा, तो कोड के लिए उचित दस्तावेज लिखें (हाँ, लंबा रास्ता)। एक सकारात्मक उदाहरण के रूप में, मैं Apple के iOS डॉक्स दे सकता हूं। वे उपयोगकर्ता के लिए हमेशा अपनी कक्षाओं को ठीक से विस्तारित करने के लिए पर्याप्त नहीं होते हैं, लेकिन वे कम से कम कुछ जानकारी विरासत में शामिल करते हैं। जो सबसे अधिक एपीआई के लिए कह सकता हूं, उससे अधिक है।
  • चौथा, वास्तव में अपने स्वयं के वर्ग का विस्तार करने की कोशिश करें, यह सुनिश्चित करने के लिए कि यह काम करता है। मैं एपीआई में कई नमूनों और परीक्षणों को शामिल करने का एक बड़ा समर्थक हूं, और जब आप एक परीक्षण कर रहे होते हैं, तो आप विरासत श्रृंखलाओं का भी परीक्षण कर सकते हैं: वे आपके अनुबंध का एक हिस्सा हैं!
  • पांचवीं, ऐसी स्थितियों में जब आप संदेह में हों, यह इंगित करें कि कक्षा का विस्तार करने का मतलब नहीं है और ऐसा करना एक बुरा विचार है (tm)। संकेत दें कि आपको ऐसे अनपेक्षित उपयोग के लिए जवाबदेह नहीं ठहराया जाना चाहिए, लेकिन फिर भी कक्षा को सील न करें। जाहिर है, यह उन मामलों को कवर नहीं करता है जब कक्षा को 100% सील किया जाना चाहिए।
  • अंत में, जब एक वर्ग को सील करते हैं, तो एक इंटरमीडिएट हुक के रूप में एक इंटरफ़ेस प्रदान करें, ताकि ग्राहक वर्ग के अपने स्वयं के संशोधित संस्करण को "फिर से लिखना" कर सके और आपके 'सील' वर्ग के आसपास काम कर सके। इस तरह, वह अपने कार्यान्वयन के साथ सीलबंद वर्ग को बदल सकता है। अब, यह स्पष्ट होना चाहिए, क्योंकि यह अपने सरलतम रूप में ढीली युग्मन है, लेकिन यह अभी भी एक उल्लेख के लायक है।

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


3

एक वर्ग न तो अंतिम / सील होना चाहिए और न ही सार:

  • यह अपने आप उपयोगी है, अर्थात उस वर्ग के उदाहरणों के लिए फायदेमंद है।
  • यह उस वर्ग के लिए फायदेमंद है जो अन्य वर्गों का उपवर्ग / आधार वर्ग है।

उदाहरण के लिए, ObservableCollection<T>कक्षा को C # में लें । यह केवल घटनाओं को बढ़ाने के लिए एक के सामान्य संचालन को जोड़ने की आवश्यकता है Collection<T>, यही कारण है कि यह उपवर्ग है Collection<T>Collection<T>अपने आप में एक व्यवहार्य वर्ग है, और इसलिए यह ObservableCollection<T>


अगर मैं इसका प्रभारी होता, तो शायद CollectionBase(अमूर्त), Collection : CollectionBase(सीलबंद), ObservableCollection : CollectionBase(सीलबंद) करता। यदि आप संग्रह <T> को करीब से देखते हैं, तो आप देखेंगे कि यह एक आधा-मिश्रित सार वर्ग है।
निकोलस रिपब्लिक

2
केवल दो के बजाय तीन कक्षाएं होने से आपको क्या फायदा होगा? इसके अलावा, Collection<T>"आधा-मिश्रित सार वर्ग" कैसा है?
FishBasketGordo

Collection<T>संरक्षित विधियों और संपत्तियों के माध्यम से बहुत से निर्दोषों को उजागर करता है, और स्पष्ट रूप से विशेष संग्रह के लिए एक आधार वर्ग होना चाहिए। लेकिन यह स्पष्ट नहीं है कि आप अपना कोड कहाँ रखने वाले हैं, क्योंकि वहाँ कोई सार तरीके लागू नहीं होते हैं। ObservableCollectionइनहेरिट करता है Collectionऔर सील नहीं किया जाता है, इसलिए आप फिर से इनहेरिट कर सकते हैं। और आप Itemsसंरक्षित संपत्ति तक पहुंच सकते हैं, जिससे आप घटनाओं को बढ़ाए बिना संग्रह में आइटम जोड़ सकते हैं ... अच्छा।
निकोलस रिपब्लिक

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

3

अंतिम / मुहरबंद वर्गों के साथ समस्या यह है कि वे एक ऐसी समस्या को हल करने की कोशिश कर रहे हैं जो अभी तक नहीं हुई है। यह तभी उपयोगी है जब समस्या मौजूद है, लेकिन यह निराशाजनक है क्योंकि एक तृतीय-पक्ष ने प्रतिबंध लगाया है। शायद ही कभी सीलिंग क्लास एक मौजूदा समस्या को हल करता है, जिससे यह तर्क करना मुश्किल हो जाता है कि यह उपयोगिता है।

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

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


1
सॉफ्टवेयर में अंतिम मोहरबंद सामान "मुझे इस कोड के भविष्य के रखरखाव पर मेरी इच्छा को लागू करने की आवश्यकता महसूस होती है" की समस्या का समाधान करता है।
काज

OOP में अंतिम / सील कुछ जोड़ा नहीं गया था, क्योंकि मुझे याद नहीं है कि जब मैं छोटा था, तो यह चारों ओर था। यह एक तरह के विचार के बाद लगता है।
रिएक्टगुलर

OOP सिस्टम में टूलकिन प्रक्रिया के रूप में अंतिम रूप देने से पहले OOP को C ++ और Java जैसी भाषाओं के साथ डंप किया गया। प्रोग्रामर स्मॉलटाकल में काम करते हैं, अधिकतम लचीलेपन के साथ लिस्प: कुछ भी बढ़ाया जा सकता है, हर समय नए तरीके जोड़े जाते हैं। फिर, सिस्टम की संकलित छवि एक अनुकूलन के अधीन है: एक धारणा बनाई गई है कि सिस्टम अंतिम उपयोगकर्ताओं द्वारा विस्तारित नहीं किया जाएगा, और इसलिए इसका अर्थ है कि विधि प्रेषण को किस तरीकों का जायजा लेने के आधार पर अनुकूलित किया जा सकता है और अब कक्षाएं मौजूद हैं
काज

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

सिर्फ इसलिए कि यह खुद को कुछ घोषणाओं के रूप में प्रकट करता है जिन्हें आपको कोड में डालना है इसका मतलब यह नहीं है कि यह एक ही बात नहीं है।
काज

2

ऑब्जेक्ट सिस्टम में "सीलिंग" या "फाइनल करना" कुछ अनुकूलन के लिए अनुमति देता है, क्योंकि पूरा प्रेषण ग्राफ ज्ञात है।

यह कहना है, हम प्रदर्शन के लिए व्यापार-बंद के रूप में सिस्टम को किसी और चीज़ में बदलना मुश्किल बनाते हैं। (यह सबसे अनुकूलन का सार है।)

अन्य सभी मामलों में, यह एक नुकसान है। सिस्टम डिफ़ॉल्ट रूप से खुला और एक्स्टेंसिबल होना चाहिए। सभी वर्गों के लिए नए तरीकों को जोड़ना आसान होना चाहिए, और मनमाने ढंग से विस्तार करना चाहिए।

हम भविष्य के विस्तार को रोकने के लिए कदम उठाकर आज कोई नई कार्यक्षमता हासिल नहीं करते हैं।

इसलिए यदि हम इसे स्वयं की रोकथाम के लिए करते हैं, तो हम जो कर रहे हैं, वह भविष्य के अनुरक्षकों के जीवन को नियंत्रित करने का प्रयास कर रहा है। यह अहंकार के बारे में है। "यहां तक ​​कि जब मैं यहां काम नहीं करता, तब भी इस कोड को बनाए रखा जाएगा, धिक्कार है!"


1

परीक्षा की कक्षाएं मन में आने लगती हैं। ये ऐसी कक्षाएं हैं जिन्हें प्रोग्रामर / टेस्टर पूरा करने के लिए एक स्वचालित फैशन या "एट विल" में कहते हैं। मुझे यकीन नहीं है कि मैंने कभी भी परीक्षण के समाप्त वर्ग के बारे में देखा या सुना है जो निजी है।


क्या बात कर रहे हो किस तरह से परीक्षण कक्षाओं को अंतिम / सील / सार नहीं होना चाहिए?

1

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

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

यह कक्षाओं के विस्तार के लिए एक उत्कृष्ट अवसर है।

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

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

इस स्टैक के शीर्ष पर मैं एक ग्राहक-विशिष्ट परत रखता हूँ जो ग्राहक की ज़रूरत के अनुसार डेटा फ़ाइल संरचना को लागू करता है।

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

तो संरचना इस तरह दिखती है:

Base
 Function1
  Customer1
  Customer2
 Function2
 ...

मेरा प्राथमिक बिंदु यह है कि कोड को इस तरह से तैयार करके मैं मुख्य रूप से कोड पुन: उपयोग के लिए विरासत का उपयोग कर सकता हूं।

मेरा कहना है कि मैं किसी भी कारण के बारे में सोच नहीं सकता कि तीन परतें हैं।

मैंने कई बार दो परतों का उपयोग किया है, उदाहरण के लिए एक सामान्य Tableवर्ग है जो डेटाबेस तालिका प्रश्नों को Tableलागू करता है जबकि प्रत्येक तालिका के विशिष्ट विवरणों को लागू करने के लिए उप-वर्गों enumको परिभाषित करने के लिए खेतों का उपयोग करके । कक्षा enumमें परिभाषित इंटरफ़ेस को लागू करने देना Tableसभी प्रकार की समझ में आता है।


1

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


1
यह एक अच्छी टिप्पणी है, लेकिन सीधे सवाल का जवाब नहीं देता है। कृपया अपने विचारों को यहां विस्तार देने पर विचार करें।

1

मैं आपके विचार से सहमत हूं। मुझे लगता है कि जावा में, डिफ़ॉल्ट रूप से, कक्षाओं को "अंतिम" घोषित किया जाना चाहिए। यदि आप इसे अंतिम नहीं बनाते हैं, तो विशेष रूप से इसे तैयार करें और इसे विस्तार के लिए दस्तावेज करें।

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

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

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

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