2012-03-24 22 views
115

संभव डुप्लिकेट:
Why should the interface for a Java class be prefered?पॉलिमॉर्फिज्म: "ArrayList list = new ArrayList" के बजाय "सूची सूची = नया ArrayList" का उपयोग क्यों करें?

मैं List से

List<Object> list = new ArrayList<Object>(); 

ArrayList inherits उपयोग कब करना चाहिए, इसलिए यदि ArrayList में कुछ विशेषताएं List में नहीं हैं, तो मैंकी कुछ विशेषताओं को खो दिया होगा, है ना? और इन तरीकों तक पहुंचने का प्रयास करते समय संकलक को एक त्रुटि दिखाई देगी?

+0

ओह। मुझे माफ कर दो। क्योंकि मैं 'ऑब्जेक्ट' में बदल जाता हूं, इसलिए मैं इसे भूल जाता हूं। – hqt

+6

@ डफिमो - वह सवाल पूछ रहा है कि क्यों नई सूची () 'काम नहीं करती है। यह एक बिल्कुल अलग सवाल है। –

+2

यह एक डुप्लिकेट प्रश्न नहीं है। संभावित डुप्लिकेट में सामान्य प्रश्न है लेकिन एक विशिष्ट विवरण है। मुझे यह प्रश्न शीर्षक में अधिक प्रासंगिक/वास्तव में पूछे जाने वाले सिंक में मिलता है। – Dexters

उत्तर

205

मुख्य कारण यह है कि आप ऐसा करेंगे कि इंटरफ़ेस के विशिष्ट कार्यान्वयन से आपके कोड को डीक्यूपल करना है। जब आप इस तरह अपने कोड लिखने:

List list = new ArrayList(); 

अपने कोड के बाकी केवल जानता है कि डेटा प्रकार List है, जो बेहतर है क्योंकि यह आप आसानी से List इंटरफेस के विभिन्न कार्यान्वयन के बीच स्विच करने की अनुमति देता है की है।

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

List list = new LinkedList(); 

को
List list = new ArrayList(); 

और आप जानते हैं कि इस वजह से आप अपने कोड लिखा है List इंटरफ़ेस द्वारा प्रदान की अनुबंध का पालन करने के लिए काम करेंगे।

दूसरी ओर, यदि आप को लागू किया, LinkedList list = new LinkedList() का उपयोग कर इस तरह के एक परिवर्तन करने से अपनी लाइब्रेरी का कोर के रूप में आसान नहीं होगा, के रूप में कोई गारंटी नहीं कि अपने कोड के बाकी तरीकों का उपयोग नहीं कर सकता है LinkedList कक्षा के लिए विशिष्ट।

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

+4

स्पष्ट स्पष्टीकरण। :) – coder247

+44

बहुत से लोग इसका उल्लेख करने में असफल रहते हैं कि इसे स्थानीय चर के रूप में इसे ArrayList सूची = new ArrayList() के माध्यम से तुरंत चालू करने के लिए स्वीकार्य है। विधि हस्ताक्षर में या कक्षा स्तर चर के प्रकार के रूप में सूची इंटरफ़ेस का उपयोग करना केवल वास्तव में फायदेमंद है। यदि आपको बाद में वापस जाना है और स्थानीय विधि घोषणा को बदलना है तो कौन परवाह करता है? पूरा लाभ तब आता है जब किसी अन्य विधियों या पुस्तकालयों आदि को सूची का खुलासा किया जाता है। – GreenieMeanie

+5

यह सच है, इसे इंगित करने के लिए धन्यवाद। असल में, अब जब मैं इसके बारे में सोचता हूं, तो संभवतः प्रोग्रामर के बजाए क्लाइंट के दृष्टिकोण से उदाहरण देने के लिए यह अधिक समझदार होता। दोनों स्थितियों में, 'सूची सूची = नया ArrayList()' का उपयोग करना यह सुनिश्चित करने का विषय है कि आप मौजूदा कोड को तोड़ नहीं देते हैं। –

63

इसे इंटरफ़ेस के लिए प्रोग्रामिंग कहा जाता है। यदि आप भविष्य में सूची के किसी अन्य कार्यान्वयन में जाना चाहते हैं तो यह सहायक होगा। यदि आप ArrayList में कुछ विधियां चाहते हैं तो आपको ArrayList a = new ArrayList() के कार्यान्वयन के लिए प्रोग्राम करना होगा।

6

यह आपको कुछ लिखने के लिए सक्षम बनाता है: बाद में

void doSomething() { 
    List<String>list = new ArrayList<String>(); 
    //do something 
} 

, आप करने के लिए इसे बदलने के लिए चाहते हो सकता है:

void doSomething() { 
    List<String>list = new LinkedList<String>(); 
    //do something 
} 

विधि के बाकी को बदलने के लिए बिना।

हालांकि, अगर आप एक CopyOnWriteArrayList उदाहरण के लिए उपयोग करना चाहते हैं, तो आप इस तरह के रूप में यह घोषणा करने के लिए, और एक सूची के रूप में नहीं की आवश्यकता होगी अगर आप अपने अतिरिक्त तरीकों (उदाहरण के लिए addIfAbsent) उपयोग करना चाहता था:

void doSomething() { 
    CopyOnWriteArrayList<String>list = new CopyOnWriteArrayList<String>(); 
    //do something, for example: 
    list.addIfAbsent("abc"); 
} 
+1

स्वीकृत उत्तर की @ ग्रीनमीनी टिप्पणी के अनुसार, यह परिवर्तन कोई फर्क नहीं पड़ता क्योंकि यह एक स्थानीय चर है। – Ram

5

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

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

2

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

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

17

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

public ArrayList getList(); 

तो फिर तुम, करने के लिए इसे बदलने के लिए

public LinkedList getList(); 

जो कोई ArrayList list = yourClass.getList() कर रहा था उनके कोड बदलने की आवश्यकता होगी निर्णय लेते हैं। दूसरी ओर, यदि आप ऐसा करेंगे,

public List getList(); 

कार्यान्वयन को बदलने से आपका एपीआई के उपयोगकर्ताओं के लिए कुछ भी नहीं बदलता है।

+0

yourClass.getList() मुझे लगता है कि मैं सबसे व्यावहारिक उपयोग मामले में आया हूं। बहुत बहुत धन्यवाद :) –

4

मुझे लगता है कि आपके प्रश्न के मूल कारण है कि करने के लिए program to an interface, not to an implementation

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

10

मुझे लगता है कि @ tsatiz का जवाब ज्यादातर सही है (कार्यान्वयन के बजाय एक इंटरफ़ेस प्रोग्रामिंग)। हालांकि, इंटरफ़ेस पर प्रोग्रामिंग करके आप कोई कार्यक्षमता खो देंगे नहीं। मुझे समझाने दो।

आप के रूप में एक List<type> list = new ArrayList<type> अपने चर घोषित यदि आप वास्तव में खो ArrayList के किसी भी कार्यक्षमता नहीं है।आपको बस list को ArrayList पर डालना है। यहाँ एक उदाहरण है:

List<String> list = new ArrayList<String>(); 
((ArrayList<String>) list).ensureCapacity(19); 

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

आशा है कि मदद करता है!

+0

यह एक बहुत ही आसान और स्पष्ट है। – CopsOnRoad

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