2008-09-29 3 views
66

PMD के लिए उल्लंघन की रिपोर्ट जाएगा:जावा क्लास के लिए इंटरफ़ेस को क्यों पसंद किया जाना चाहिए?

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

उल्लंघन था " 'ArrayList' की तरह कार्यान्वयन प्रकार के प्रयोग से बचें, बजाय इंटरफ़ेस का उपयोग"।

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

क्यों List के साथ बाद ArrayList के बजाय इस्तेमाल किया जाना चाहिए:

निम्न पंक्ति उल्लंघन को ठीक नहीं होगा?

+0

भी देखें http: // stackoverflow।कॉम/प्रश्न/383947/क्या-यह-मतलब-टू-प्रोग्राम-टू-ए-इंटरफ़ेस – Raedwald

उत्तर

73

कंक्रीट प्रकारों पर इंटरफेस का उपयोग करना अच्छा encapsulation और आपके कोड को ढीला करने के लिए महत्वपूर्ण है।

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

इस विषय पर good article है।

उम्मीद है कि यह मदद करता है!

27

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

5

ऐरेलिस्ट और लिंक्डलिस्ट एक सूची के दो कार्यान्वयन हैं, जो वस्तुओं का ऑर्डर किया गया संग्रह है। तर्कसंगत यह कोई फर्क नहीं पड़ता कि आप ArrayList या LinkedList का उपयोग करते हैं, इसलिए आपको उस प्रकार को बाधित नहीं करना चाहिए।

यह कहता है कि संग्रह, संग्रह और सूची, जो अलग-अलग चीजें हैं (सूची सॉर्टिंग का मतलब है, संग्रह नहीं है)।

0

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

class Counter { 
    static int sizeOf(List<?> items) { 
     return items.size(); 
    } 
} 

इस मामले में आवश्यक इंटरफ़ेस का उपयोग है। क्योंकि मैं के आकार को गिनना चाहता हूं, हर संभव कार्यान्वयन मेरे स्वयं के कस्टम सहित। class MyList extends AbstractList<String>...

+0

यदि आप ArrayList जैसे कार्यान्वयन के लिए कोड करते हैं, तो हर संभावना है कि आप कार्यान्वयन के तरीकों का उपयोग कर सकते हैं, भले ही आप ऐसा कर सकें इंटरफ़ेस विधियों के साथ बात। यह कार्यान्वयन के लिए आपके कोड को बाध्य करेगा - बाद में कार्यान्वयन के बीच स्विच करना कठिन बना देता है। – Champ

1

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

हालांकि ...

स्थानीय चर घोषणाओं में, यह यह करने के लिए थोड़ा समझ में आता है:

public void someMethod() { 
List theList = new ArrayList(); 
//do stuff with the list 
} 

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

10

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

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

ब्याज के लिए मैंने एक प्रयोग चलाया जिसने दस लाख अनुक्रमिक पहुंच को 1 मिलियन लंबाई ArrayList तक पहुंचाया। मेरे 2.4 गीगा मैकबुक पर, एक सूची इंटरफ़ेस के माध्यम से ऐरेलिस्ट को एक्सेस करने पर औसतन 2.10 सेकेंड लगते थे, जब इसे ऐरेलिस्ट के प्रकार की घोषणा करते हुए औसत 1.67 सेकेंड लगते थे।

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

+0

@ ओवेन: +5 अंतर्दृष्टि पुन: प्रदर्शन अंतर ... बहुत अप्रत्याशित –

+2

यह उत्तर हालांकि दिखाता है कि ओवरहेड बहुत छोटा हो सकता है: http://stackoverflow.com/questions/890687/overhead-of-implementing-an-interface/891096 # 891096 – Raedwald

+1

वाह! दस बिलियन एक्सेस के लिए 0.5 सेकंड, यानी 1 इंटरफ़ेस एक्सेस आधे नैनोसेकंड क्लास एक्सेस की तुलना में धीमी है! यह निश्चित रूप से कभी भी इंटरफेस का उपयोग करने का एक कारण नहीं है। – Ingo

1

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

0

स्प्रिंग ढांचे इंटरफेस की अवधारणा वास्तव में अच्छी तरह से लागू होता है - http://www.springframework.org/

स्प्रिंग विन्यास फाइल के माध्यम से एक ठोस वर्ग के लिए कार्यान्वयन की आपूर्ति और इतने ठोस वर्ग बिल्कुल कार्यान्वयन के बारे में कुछ पता नहीं है।

वसंत का अध्ययन जावा में इंटरफ़ेस आधारित प्रोग्रामिंग के फायदों का उदाहरण देता है।

1

बाद वाले को ArrayList के बजाय सूची का उपयोग क्यों किया जाना चाहिए?

यह एक अच्छी आदत है: कार्यान्वयन

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

List<Object> list = new LinkedList<Object>(); 
/* Doubly-linked list implementation of the List and Deque interfaces. 
Implements all optional list operations, and permits all elements (including null).*/ 

या

List<Object> list = new CopyOnWriteArrayList<Object>(); 
/* A thread-safe variant of ArrayList in which all mutative operations 
(add, set, and so on) are implemented by making a fresh copy of the underlying array.*/ 

या

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

/* The Stack class represents a last-in-first-out (LIFO) stack of objects.*/ 

या

कुछ अन्य List विशिष्ट कार्यान्वयन।

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

संबंधित एसई प्रश्न:

What does it mean to "program to an interface"?

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

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