2010-07-22 11 views
30

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

तो जब आप एक इंटरफेस लागू करते हैं और आप सुपरक्लास का विस्तार कब करते हैं?

+3

मुझे लगता है कि आपको इसमें भी कारक बनाना चाहिए - पुन: उपयोग के मामले में एक महत्वपूर्ण अवधारणा है - http://www.artima.com/designtechniques/compoinh.html – Jon

उत्तर

34

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

उपयोग एक सार वर्ग अगर आप इतना है कि endusers यह बार-बार फिर से लिखने के बिना इसे पुनः उपयोग कर सकते गैर सार तरीकों में डिफ़ॉल्ट व्यवहार परिभाषित करना चाहते हैं। एक वर्ग से केवल एक अन्य वर्ग से बढ़ाया जा सकता है। के साथ एक सार वर्ग केवल अमूर्त विधियों को एक इंटरफ़ेस के रूप में अच्छी तरह से परिभाषित किया जा सकता है। किसी भी अमूर्त विधि के बिना एक अमूर्त वर्ग Template Method पैटर्न के रूप में पहचाने जाने योग्य है (कुछ असली दुनिया उदाहरणों के लिए this answer देखें)।

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

+1

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

0

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

3

कोई नहीं?

http://mindprod.com/jgloss/interfacevsabstract.html

संपादित करें: मैं एक लिंक

यहाँ एक स्थिति है की तुलना में अधिक आपूर्ति करनी चाहिए। नीचे कार उदाहरण पर निर्माण करने के लिए, पर विचार यह

interface Drivable { 
    void drive(float miles); 
} 

abstract class Car implements Drivable { 
    float gallonsOfGas; 
    float odometer; 
    final float mpg; 
    protected Car(float mpg) { gallonsOfGas = 0; odometer = 0; this.mpg = mpg; } 
    public void addGas(float gallons) { gallonsOfGas += gallons; } 
    public void drive(float miles) { 
     if(miles/mpg > gallonsOfGas) throw new NotEnoughGasException(); 
     gallonsOfGas -= miles/mpg; 
     odometer += miles; 
    } 
} 

class LeakyCar extends Car { // still implements Drivable because of Car 
    public addGas(float gallons) { super.addGas(gallons * .8); } // leaky tank 
} 

class ElectricCar extends Car { 
    float electricMiles; 
    public void drive(float miles) { // can we drive the whole way electric? 
     if(electricMiles > miles) { 
      electricMiles -= miles; 
      odometer += miles; 
      return;     // early return here 
     } 
     if(electricMiles > 0) { // exhaust electric miles first 
      if((miles-electricMiles)/mpg > gallonsOfGas) 
       throw new NotEnoughGasException(); 
      miles -= electricMiles; 
      odometer += electricMiles; 
      electricMiles = 0; 
     } 
     // finish driving 
     super.drive(miles); 
    } 
} 
+4

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

+0

एक अच्छे लिंक के लिए +1 – naikus

0

मुझे लगता है मैं क्लासिक कार उदाहरण दे देंगे।

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

आप एक कार वर्ग है, तो आप उसके बाद कार वर्ग एक ट्रक, या बस बनाने के लिए विस्तार कर सकते हैं। दूसरे शब्दों में, आप बेस या सुपर क्लास के गुणों को रखते हुए उप वर्गों में नए गुण जोड़ते हैं।

+0

मैं तर्क दूंगा कि कार एक अमूर्त वर्ग होना चाहिए और इंटरफ़ेस नहीं होना चाहिए। फोर्ड, चेवी अमूर्त कार वर्ग का विस्तार करना चाहिए। – Thunderhashy

+0

वह कह रहा था कि आप कर सकते हैं, ऐसा नहीं करना चाहिए।अंगूठे का मेरा नियम है "कक्षाएं चीजें हैं, इंटरफेस करते हैं" - इसलिए, मेरे पास – corsiKa

+0

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

1

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

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

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

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

5

पर एक इंटरफ़ेस का उपयोग व्यवहार को परिभाषित करें। उपयोगकर्ता (सार) कक्षाएं (और उप-वर्ग) कार्यान्वयन प्रदान करने के लिए। वे पारस्परिक रूप से विशिष्ट नहीं हैं; वे सभी एक साथ काम कर सकते हैं।

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

1

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

3

सार कक्षाओं और इंटरफेस का उपयोग करने का मुख्य कारण अलग-अलग हैं।

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

यह एक बुरा उदाहरण हो सकता है, लेकिन जावा ढांचे में अमूर्त वर्गों का सबसे स्पष्ट उपयोग java.io कक्षाओं के भीतर है। OutputStream बाइट्स की एक धारा है। जहां वह धारा पूरी तरह से निर्भर करती है, उस पर निर्भर करता है कि OutputStream के उप-वर्ग पर आप उपयोग कर रहे हैं ... FileOutputStream, PipedOutputStream, java.net.Socket की getOutputStream विधि से निर्मित आउटपुट स्ट्रीम ...

नोट: java.io अन्य धाराओं/पाठकों/लेखकों में धाराओं को लपेटने के लिए सजावटी पैटर्न का भी उपयोग करता है।

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

इंटरफेस का सबसे स्पष्ट उपयोग संग्रह ढांचे के भीतर है।

मुझे परवाह नहीं है एक List कैसे कहते हैं /, तत्वों को हटा इतने लंबे समय के रूप में मैं डाल दिया और तत्वों पाने के लिए add(something) और get(0) कॉल कर सकते हैं। यह एक सरणी (ArrayList, CopyOnWriteArrayList), लिंक्ड सूची (LinkedList), आदि ... का उपयोग कर सकते

अन्य लाभ इंटरफेस का उपयोग करने में है कि एक वर्ग एक से अधिक को लागू कर सकते हैं। LinkedListListऔरDeque दोनों का कार्यान्वयन है।

12

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

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

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

2

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

संबंधित मुद्दे