oop - इंटरफेस बनाम बेस क्लास




interface language-agnostic (20)

इंटरफेस

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

बेस कक्षाएं

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

मुझे इंटरफ़ेस का उपयोग कब करना चाहिए और मुझे बेस क्लास का उपयोग कब करना चाहिए?

यदि मैं वास्तव में विधियों के मूल कार्यान्वयन को परिभाषित नहीं करना चाहता हूं तो क्या यह हमेशा एक इंटरफ़ेस होना चाहिए?

अगर मेरे पास कुत्ता और बिल्ली वर्ग है। मैं पेटबेस के बजाय आईपेट क्यों लागू करना चाहूंगा? मैं आइशेड या आईबार्क (IMakesNoise?) के लिए इंटरफेस रखने में समझ सकता हूं, क्योंकि उन्हें पालतू जानवरों के आधार पर पालतू जानवरों पर रखा जा सकता है, लेकिन मुझे समझ में नहीं आता कि सामान्य पालतू जानवर के लिए कौन सा उपयोग करना है।


आइए कुत्ते और बिल्ली वर्ग का अपना उदाहरण लें, और चलिए सी # का उपयोग करके चित्रित करते हैं:

एक कुत्ते और एक बिल्ली दोनों जानवर हैं, विशेष रूप से, चौगुनी स्तनधारियों (जानवरों को बहुत सामान्य हैं)। आइए मान लें कि आपके पास एक अमूर्त वर्ग स्तनधारी है, दोनों के लिए:

public abstract class Mammal

इस बेस क्लास में शायद डिफ़ॉल्ट विधियां होंगी जैसे कि:

  • चारा
  • दोस्त

जिनमें से सभी व्यवहार हैं जो कि प्रजातियों के बीच समान कार्यान्वयन कम या कम हैं। इसे परिभाषित करने के लिए आपके पास होगा:

public class Dog : Mammal
public class Cat : Mammal

अब मान लीजिए कि अन्य स्तनधारियां हैं, जिन्हें हम आम तौर पर एक चिड़ियाघर में देखेंगे:

public class Giraffe : Mammal
public class Rhinoceros : Mammal
public class Hippopotamus : Mammal

यह अभी भी वैध होगा क्योंकि कार्यक्षमता के मूल पर Feed() और Mate() अभी भी वही होंगे।

हालांकि, जिराफ, rhinoceros, और hippos बिल्कुल जानवर नहीं हैं कि आप पालतू जानवरों को बाहर कर सकते हैं। यही वह जगह है जहां एक इंटरफ़ेस उपयोगी होगा:

public interface IPettable
{
    IList<Trick> Tricks{get; set;}
    void Bathe();
    void Train(Trick t);
}

उपरोक्त अनुबंध के लिए कार्यान्वयन बिल्ली और कुत्ते के बीच समान नहीं होगा; अपने कार्यान्वयन को एक अमूर्त वर्ग में विरासत में रखने के लिए एक बुरा विचार होगा।

आपके कुत्ते और बिल्ली परिभाषाओं को अब इस तरह दिखना चाहिए:

public class Dog : Mammal, IPettable
public class Cat : Mammal, IPettable

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

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


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


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

चारों की गिरोह ने अपनी पुस्तक में कहा "क्योंकि विरासत अपने माता-पिता के कार्यान्वयन के ब्योरे के लिए एक उप-वर्ग का खुलासा करती है, अक्सर यह कहा जाता है कि 'विरासत टूटना encapsulation"। मुझे विश्वास है कि यह सच है।


इंटरफेस छोटा होना चाहिए। वास्तव में छोटा। यदि आप वास्तव में अपनी वस्तुओं को तोड़ रहे हैं, तो आपके इंटरफेस में शायद कुछ ही विशिष्ट विधियों और गुण होंगे।

सार वर्ग शॉर्टकट हैं। क्या ऐसी चीजें हैं जो पेटबेस शेयर के सभी डेरिवेटिव्स हैं जिन्हें आप एक बार कोड कर सकते हैं और साथ किया जा सकता है? यदि हां, तो यह एक अमूर्त वर्ग के लिए समय है।

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

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

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


इंटरफेस पर बेस क्लासेस के मामले को Submain .NET कोडिंग दिशानिर्देशों में अच्छी तरह से समझाया गया था:

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

चूंकि इंटरफेस कार्यान्वयन विरासत का समर्थन नहीं करते हैं, इसलिए वर्गों पर लागू पैटर्न इंटरफेस पर लागू नहीं होता है। एक इंटरफ़ेस में कोई विधि जोड़ना बेस क्लास में एक सार विधि जोड़ने के बराबर है; इंटरफ़ेस लागू करने वाली कोई भी कक्षा टूट जाएगी क्योंकि कक्षा नई विधि को लागू नहीं करती है। इंटरफेस निम्नलिखित स्थितियों में उपयुक्त हैं:

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

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


खैर, जोश ब्लोच ने खुद को प्रभावी जावा 2 डी में कहा:

अमूर्त वर्गों पर इंटरफेस पसंद करते हैं

कुछ मुख्य बिंदु:

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

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

  • इंटरफेस nonhierarchical प्रकार ढांचे के निर्माण की अनुमति देते हैं । टाइप करें पदानुक्रम कुछ चीजों को व्यवस्थित करने के लिए बहुत अच्छे हैं, लेकिन अन्य चीजें एक कठोर पदानुक्रम में अच्छी तरह से नहीं आती हैं।

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

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

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

पीएस .: किताब खरीदें। यह बहुत अधिक विस्तृत है।


जब मैंने पहली बार ऑब्जेक्ट उन्मुख प्रोग्रामिंग के बारे में सीखना शुरू किया, तो मैंने सामान्य व्यवहार साझा करने के लिए विरासत का उपयोग करने की आसान और संभवतः सामान्य गलती की - यहां तक ​​कि उस व्यवहार को वस्तु की प्रकृति के लिए आवश्यक नहीं था।

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

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

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

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

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


जुआन,

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

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

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

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

तो अगर आप मेरे जैसे सोचते हैं तो आप निश्चित रूप से कहेंगे कि बिल्ली और कुत्ते आईपीटेबल हैं। यह एक विशेषता है जो दोनों से मेल खाती है।

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

कहो मैं सभी पशु वर्गों को इकट्ठा करना चाहता हूं और उन्हें अपने सन्दूक कंटेनर में रखना चाहता हूं।

या क्या उन्हें स्तनधारियों की आवश्यकता है? शायद हमें किसी प्रकार का क्रॉस पशु दुग्ध कारखाना चाहिए?

क्या उन्हें भी एक साथ जोड़ने की ज़रूरत है? क्या यह सिर्फ इतना पता है कि वे दोनों आईपीएटेबल हैं?

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

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


मेरे पास एक मोटा नियम है

कार्यक्षमता: सभी भागों में अलग होने की संभावना: इंटरफ़ेस।

डेटा, और कार्यक्षमता, भागों ज्यादातर एक ही होंगे, भागों अलग: अमूर्त वर्ग।

डेटा, और कार्यक्षमता, वास्तव में काम कर रही है, अगर केवल मामूली परिवर्तन के साथ विस्तारित: सामान्य (ठोस) वर्ग

डेटा और कार्यक्षमता, कोई बदलाव नहीं किया गया: अंतिम संशोधक के साथ सामान्य (ठोस) वर्ग।

डेटा, और शायद कार्यक्षमता: केवल पढ़ने के लिए: enum सदस्यों।

यह बहुत मोटा और तैयार है और बिल्कुल सख्ती से परिभाषित नहीं है, लेकिन इंटरफेस से एक स्पेक्ट्रम है जहां सब कुछ enums में बदलना है, जहां सबकुछ केवल पढ़ने-योग्य फ़ाइल की तरह तय किया जाता है।


यह भी ध्यान रखें कि ओओ में दूर जाने के लिए ( ब्लॉग देखें ) और हमेशा आवश्यक व्यवहार के आधार पर वस्तुओं का मॉडल करें, यदि आप एक ऐप डिज़ाइन कर रहे थे, जहां आपको केवल एक ही व्यवहार था जो जानवर के लिए एक सामान्य नाम और प्रजाति थी तो आपको केवल आवश्यकता होगी एक वर्ग पशु नाम के लिए एक संपत्ति के साथ, दुनिया में हर संभव जानवर के लिए लाखों कक्षाओं के बजाय।


यहां इंटरफ़ेस और बेस क्लास का मूल और सरल definiton है:

  • बेस क्लास = ऑब्जेक्ट विरासत।
  • इंटरफ़ेस = कार्यात्मक विरासत।

चियर्स


Prefer interfaces over abstract classes

Rationale, the main points to consider [two already mentioned here] are :

  • Interfaces are more flexible, because a class can implement multiple interfaces. Since Java does not have multiple inheritance, using abstract classes prevents your users from using any other class hierarchy. In general, prefer interfaces when there are no default implementations or state. Java collections offer good examples of this (Map, Set, etc.).
  • Abstract classes have the advantage of allowing better forward compatibility. Once clients use an interface, you cannot change it; if they use an abstract class, you can still add behavior without breaking existing code. If compatibility is a concern, consider using abstract classes.
  • Even if you do have default implementations or internal state, consider offering an interface and an abstract implementation of it . This will assist clients, but still allow them greater freedom if desired [1].
    Of course, the subject has been discussed at length elsewhere [2,3].

[1] It adds more code, of course, but if brevity is your primary concern, you probably should have avoided Java in the first place!

[2] Joshua Bloch, Effective Java, items 16-18.

[3] http://www.codeproject.com/KB/ar ...


@Joel: Some languages (eg, C++) allow multiple-inheritance.


An inheritor of a base class should have an "is a" relationship. Interface represents An "implements a" relationship. So only use a base class when your inheritors will maintain the is a relationship.


Conceptually, an Interface is used to formally and semi-formally define a set of methods that an object will provide. Formally means a set of method names and signatures, semi-formally means human readable documentation associated with those methods. Interfaces are only descriptions of an API (after all, API stands for Application Programmer Interface ), they can't contain any implementation, and it's not possible to use or run an Interface. They only make explicit the contract of how you should interact with an object.

Classes provide an implementation, they can declare that they implement zero, one or more Interfaces. If a Class is intended to be inherited, the convention is to prefix the Class name with "Base".

There is a distinction between a Base Class and an Abstract Base Classes (ABC). ABCs mix interface and implementation together. Abstract outside of computer programming means "summary", that is "Abstract == Interface". An Abstract Base Class can then describe both an interface, as well as an empty, partial or complete implementation that is intended to be inherited.

Opinions on when to use Interfaces versus Abstract Base Classes versus just Classes is going to vary wildly based on both what you are developing, and which language you are developing in. Interfaces are often associated only with statically typed languages such as Java or C#, but dynamically typed languages can also have Interfaces and Abstract Base Classes. In Python for example, the distinction is made clear between a Class, which declares that it implements an Interface, and an object, which is an instance of a Class, and is said to provide that Interface. It's possible in a dynamic language that two objects that are both instances of the same Class, can declare that they provide completely different interfaces. In Python this is only possible for object attributes, while methods are shared state between all objects of a Class. However in Ruby, objects can have per-instance methods, so it's possible that the Interface between two objects of the same Class can vary as much as the programmer desires (however, Ruby doesn't have any explicit way of declaring Interfaces).

In dynamic languages the Interface to an object is often implicitly assumed, either by introspecting an object and asking it what methods it provides (Look Before You Leap) or preferably by simply attempting to use the desired Interface on an object and catching exceptions if the object doesn't provide that Interface (Easier to Ask Forgiveness than Permission). This can lead to "false positives" where two Interfaces have the same method name but are semantically different, however the trade-off is that your code is more flexible since you don't need to over specify up-front to anticipate all possible uses of your code.


I usually don't implement either until I need one. I favor interfaces over abstract classes because that gives a little more flexibility. If there's common behavior in some of the inheriting classes I move that up and make an abstract base class. I don't see the need for both, since they essentially server the same purpose, and having both is a bad code smell (imho) that the solution has been over-engineered.


It depends on your requirements. If IPet is simple enough, I would prefer to implement that. Otherwise, if PetBase implements a ton of functionality you don't want to duplicate, then have at it.

The downside to implementing a base class is the requirement to override (or new ) existing methods. This makes them virtual methods which means you have to be careful about how you use the object instance.

Lastly, the single inheritance of .NET kills me. A naive example: Say you're making a user control, so you inherit UserControl . But, now you're locked out of also inheriting PetBase . This forces you to reorganize, such as to make a PetBase class member, instead.


Regarding C#, in some senses interfaces and abstract classes can be interchangeable. However, the differences are: i) interfaces cannot implement code; ii) because of this, interfaces cannot call further up the stack to subclass; and iii) only can abstract class may be inherited on a class, whereas multiple interfaces may be implemented on a class.





static-typing