क्या यह इंटरफेस का उपयोग न करने की बुरी आदत है? [बन्द है]


40

मैं शायद ही कभी इंटरफेस का उपयोग करता हूं और उन्हें दूसरों के कोड में सामान्य पाता हूं।

इसके अलावा, मैं अपने कोड में शायद ही कभी उप और सुपर कक्षाएं (अपनी कक्षाएं बनाते समय) बनाता हूं।

  • क्या यह बुरी बात है?
  • क्या आप इस शैली को बदलने का सुझाव देंगे?
  • क्या इस शैली का कोई दुष्प्रभाव है?
  • क्या ऐसा इसलिए है क्योंकि मैंने किसी बड़े प्रोजेक्ट पर काम नहीं किया है?

10
यह कौनसी भाषा है?

2
किस भाषा के अलावा, यह कैसी प्रतिमान है?
आर्मंडो

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

4
@ टिकट: नहीं, वास्तव में नहीं। परेशानी यह है कि C ++ कई श्रेणी की विरासत प्रदान करता है। C ++ में "इंटरफ़ेस" बहुत अधिक वैचारिक है और वास्तव में हम ज्यादातर
उसी का

2
@ टिकट नं, खासकर यदि आप एक प्रक्रियात्मक या ओओपी एक के बजाय एक कार्यात्मक भाषा में काम कर रहे हैं।
वैकल्पिक

जवाबों:


36

ऐसे कई कारण हैं जिनके कारण आप इंटरफेस का उपयोग करना चाहते हैं:

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

http://msdn.microsoft.com/en-us/library/3b5b8ezk(v=vs.80).aspx

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


13
उसकी भाषा निर्दिष्ट नहीं है, और तुम्हारा भी विशिष्ट है- उदाहरण के लिए, C ++ में, एक संरचना वास्तव में एक वर्ग से विरासत में मिल सकती है, और आप गैर-सार आधारों को गुणा कर सकते हैं।
डेडजैम

2
यदि आप # 4 को निकालते हैं तो यह उत्तर C # लगता है, लेकिन जावा से भी संबंधित है, और केवल C ++ पर लागू होता है, क्योंकि C ++ में एकाधिक वंशानुक्रम की अनुमति है।
जूना

2
इसके अलावा, मैं पिछले बयान से असहमत हूं। मुझे लगता है कि प्रोग्रामर को बहुत सारी अच्छी प्रैक्टिस करनी चाहिए लेकिन ऐसा नहीं करना चाहिए क्योंकि उन्हें लगता है कि उन्हें उनकी ज़रूरत नहीं है। मुझे लगता है कि पूछने वाला चारों ओर देखने में बहुत बुद्धिमान है, बाकी सभी को यह काम करते हुए देख रहा है, और सोच रहा है कि वह भी ऐसा कर रहा होगा, लेकिन पहले "क्यों" पूछ रहा है।
Ricket

3
@ टिकट: मेरे जवाब के चार बुलेट पॉइंट में क्यों है। यदि उन कारणों में से कोई भी लागू नहीं होता है, तो आपको इंटरफ़ेस की आवश्यकता नहीं है।
रॉबर्ट हार्वे

17

दोनों वर्ग की विरासत और इंटरफेस दोनों का अपना स्थान है। वंशानुक्रम का अर्थ है "एक" जबकि एक इंटरफ़ेस एक अनुबंध प्रदान करता है जो परिभाषित करता है कि कुछ "जैसा व्यवहार करता है"।

मैं कहूंगा कि अधिक बार इंटरफेस का उपयोग करना एक बुरा अभ्यास नहीं है। मैं वर्तमान में Bill Wagner द्वारा "प्रभावी C # - 50 आपके C # सुधारने के विशिष्ट तरीके" पढ़ रहा हूं। आइटम नंबर 22 राज्यों, और मैं बोली, "प्राथमिकता को परिभाषित करना और कार्यान्वयन को प्राथमिकता दें"।

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

बिल वैग्नर्स बुक के कुछ उद्धरण ...

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

"कोडिंग इंटरफेस अन्य डेवलपर्स को बेस क्लास प्रकारों की कोडिंग की तुलना में अधिक लचीलापन प्रदान करता है।"

"एक वर्ग के लिए एपीआई को परिभाषित करने के लिए इंटरफेस का उपयोग करना अधिक लचीलापन प्रदान करता है।"

"जब आपका प्रकार वर्ग के प्रकारों के रूप में गुणों को उजागर करता है, तो यह उस वर्ग के लिए संपूर्ण इंटरफ़ेस को उजागर करता है। इंटरफेस का उपयोग करके, आप केवल उन विधियों और गुणों को उजागर करना चुन सकते हैं जिन्हें आप उपयोग करना चाहते हैं।"

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


2
खैर, मैंने इसे पढ़ा और सोचा कि यह एक अच्छा जवाब था।
एरिक किंग

1
@ mc10 यह निश्चित नहीं है कि समस्या क्या है। उन्होंने एक पुस्तक का उल्लेख किया और उनके उत्तर के निचले आधे हिस्से में उस पुस्तक के उद्धरण हैं जो आपको स्पष्ट रूप से बताती है कि आप अपना समय बर्बाद नहीं करना चाहते हैं।
पीट

@ मैंने यह नहीं कहा कि उत्तर बुरा है, लेकिन केवल यह कि यह थोड़ा लंबा था। मुझे संदेह है कि आपको कभी-कभी पूरे उद्धरण की आवश्यकता थी।
केविनजी

3
हाहा, अगर यह tl है; डॉ, मुझे यकीन नहीं है कि आप इस पूरी StackExchange-high-quality-answer चीज़ को पसंद करने वाले हैं।
निक

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

8

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

कुछ लोग इस सर्वोत्तम अभ्यास पर विचार करते हैं, क्योंकि यह "युग्मन को कम करता है", लेकिन मैं असहमत हूं - मुझे लगता है कि यह भाषा में कमी के लिए सिर्फ एक समाधान है।


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

उदाहरण के लिए, .Net फ्रेमवर्क में कई वर्ग होते हैं जो सामान की सूची संग्रहीत करते हैं , लेकिन वे सभी उस सामान को अलग-अलग तरीकों से संग्रहीत करते हैं। इस प्रकार, यह एक सार IList<T>इंटरफेस है, जो विभिन्न तरीकों का उपयोग कर लागू किया जा सकता है समझ में आता है ।

जब आप चाहते हैं कि भविष्य में 2+ कक्षाएं विनिमेय या बदली जाने योग्य हों, तो आपको इसका उपयोग करना चाहिए। अगर भविष्य में सूचियों को संग्रहीत करने का एक नया तरीका सामने आता है AwesomeList<T>, तो आप IList<T>अपने पूरे कोड का उपयोग करते हुए, इसे बदलने के लिए उपयोग करने का AwesomeList<T>मतलब केवल कुछ सौ / हजार के बजाय कुछ दर्जन लाइनों को बदलना होगा।


5

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


4

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

परेशानी यह है कि कमजोर संकलन-समय वाली जेनरिक के साथ C # और जावा जैसी भाषाओं में, आप DRY का उल्लंघन कर सकते हैं क्योंकि एक विधि लिखने का कोई तरीका नहीं है जो एक से अधिक वर्ग के साथ सौदा कर सकता है जब तक कि सभी वर्ग एक ही आधार से वारिस न हों। C # 4's इससे निपट dynamic सकता है , हालांकि।

बात यह है, विरासत वैश्विक चर की तरह है- एक बार जब आप इसे जोड़ते हैं और आपका कोड इस पर निर्भर करता है, तो भगवान आपको इसे दूर ले जाने में मदद करते हैं। हालाँकि, आप इसे किसी भी समय जोड़ सकते हैं, और आप इसे आधार वर्ग में फेरबदल के बिना भी जोड़ सकते हैं।


1
पतन का कारण?
डेडएमजी

यकीन नहीं है, एक उत्थान है। यह एक अच्छा जवाब था।
ब्रायन बोएचेचर

3

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


3

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

तो, वास्तव में, आपका प्रश्न प्रतिमान-निर्भर (इस मामले में ओओपी) है और, आगे, वास्तव में काफी भाषा-निर्भर है (इंटरफेस के बिना ओओपी भाषाएं हैं)।


2

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


1

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

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


0

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

खराब:

class B; // forward declaration
class A
{
  B* b;
};

class B
{
  A* a;
}

बुरा नहीं:

class PartOfClassB_AccessedByA
{
};

class A
{
  PartOfClassB_AccessedByA* b;
};

class B : public PartOfClassB_AccessedByA
{
  A* a;
}

आमतौर पर A, B, PartOfClassB_AccessedByA अलग-अलग फाइलों के साथ लागू किया जाता है।


0

इंटरफ़ेस आधारित प्रोग्रामिंग कोड को अधिक लचीला और परीक्षण में आसान बनाने में मदद करती है। क्लाइंट कोड [लचीलापन] को छूने के बिना कार्यान्वयन कक्षाएं बदली जा सकती हैं। कोड का परीक्षण करते समय एक वास्तविक oInterface की जगह ले सकता है प्रोग्रामिंग आधारित कोड को अधिक लचीला और परीक्षण करने में आसान बनाने में मदद करता है। क्लाइंट कोड [लचीलापन] को छूने के बिना कार्यान्वयन कक्षाएं बदली जा सकती हैं। कोड का परीक्षण करते समय वास्तविक वस्तु को नकली वस्तुओं के साथ बदल सकते हैं [परीक्षणीयता]। नकली वस्तुओं के साथ विषय। [परीक्षणनीयता]।

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