2010-01-02 14 views
32

संभव डुप्लिकेट: एक अंतरफलक के लिए"एक इंटरफेस के लिए कार्यक्रम"। इसका क्या मतलब है?

कार्यक्रम:
What does it mean to “program to an interface”?

मुझे इस शब्द भर में आते हैं।

इसका क्या अर्थ है? वास्तविक जीवन डिजाइन परिदृश्य की अत्यधिक सराहना की जाएगी।

+1

एक और डुप्लिकेट। मुझे यह सवाल वास्तव में पसंद है, लेकिन इसे कई बार पोस्ट किया गया है ... क्या आपने खोज-बार का उपयोग करने की कोशिश की? आपको यहां बहुत सारे सुझाव मिलते हैं: http://stackoverflow.com/search?q=programming+to+interface –

उत्तर

65

बजाय एक तरीका है कि कहते हैं

मैं पर निर्भर इस विशिष्ट वर्ग अपने काम करने के लिए अपनी कक्षाओं लिखने की बस में कहें,

आप इसे इस तरह लिखते हैं कि

मैं पर किसी भी श्रेणी पर निर्भर करता हूं जो करता है यह सामग्री मेरे काम करने के लिए करता है।

पहला उदाहरण एक वर्ग है कि इसके काम करने के लिए एक विशिष्ट ठोस कार्यान्वयन पर निर्भर करता प्रतिनिधित्व करता है। स्वाभाविक रूप से, यह बहुत लचीला नहीं है।

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

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

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

+3

सरल। सटीक। दुर्भाग्य से –

+0

कोई अच्छा जवाब नहीं है। "कार्यक्रम * से * एक इंटरफ़ेस" का अर्थ है * बस * वह। इसका मतलब यह नहीं है कि आप काम करने के लिए एक विशिष्ट वर्ग पर निर्भर नहीं हो सकते हैं। आपके 'ILogger' उदाहरण के प्रति उदाहरण के रूप में, मैं कक्षाओं को java.util.logging.Logger' और 'org.apache.log4j.Logger' पर विचार करने की पेशकश करता हूं: इन दोनों बहुत लोकप्रिय लॉगिंग एपीआई * लागू नहीं होते हैं एक अलग इंटरफेस, सीधे क्लाइंट कोड से इस्तेमाल किया जा रहा है। क्लाइंट कोड जो अभी भी "इंटरफ़ेस के लिए प्रोग्रामिंग" है, 'लॉगर' वर्ग का इंटरफ़ेस। –

+1

@ Rogério बिंदु यह नहीं है कि कोई विशेष जावा क्लास एक स्पष्ट इंटरफ़ेस प्रदान करता है, लेकिन क्या आपके द्वारा लिखे गए कोड को इंटरफ़ेस के बजाय विशिष्ट वर्ग पर निर्भर करता है। यदि आप कोड लिखते हैं जो विशेष रूप से 'org.apache.log4j.Logger' पर निर्भर करता है, तो आप _ इंटरफ़ेस पर प्रोग्रामिंग नहीं करते हैं। यदि आप कोड लिखते हैं जो परवाह नहीं करता है कि प्रदान किया गया लॉगर 'java.util.logging.Logger' या' org.apache.log4j.Logger' या कोई अन्य लॉगर कार्यान्वयन है जो सामान्य इंटरफ़ेस का खुलासा करता है, तो आप _are_ प्रोग्रामिंग को इंटरफेस। –

1

मुझे लगता है कि यह एरिच गामा के मंत्रों में से एक है। मैं पहली बार वह यह वर्णित (GOF पुस्तक से पहले) नहीं मिल सकता है, लेकिन आप देख सकते हैं इस पर एक साक्षात्कार में चर्चा की: http://www.artima.com/lejava/articles/designprinciples.html

2

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

इसका यह भी मतलब है, तो आप कोड आप पर निर्भर के आंतरिक भागों के बारे में देखभाल करने के लिए जब तक इंटरफेस जैसा रहता है, नहीं है, अपने कोड के लिए सुरक्षित है (ठीक है, कम या ज्यादा ...)

तकनीकी रूप से उदाहरण के लिए जावा में "इंटरफेस" नामक भाषा अवधारणाओं जैसे बेहतर विवरण हैं।

आप और अधिक जानकारी प्राप्त करना चाहते हैं, तो आप पूछ सकते क्या "एक अंतरफलक को लागू करने" का अर्थ है ...

7

वास्तविक दुनिया उदाहरण applenty हैं। उनमें से एक:

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

एक और जावा संग्रह ढांचे से है। java.util.Collection इंटरफ़ेस है, जो size, add और remove विधियों (कई अन्य लोगों के बीच) को परिभाषित करता है। तो आप सभी प्रकार के संग्रह एक दूसरे के रूप में का उपयोग कर सकते हैं। आइए मान लें कि आपके पास निम्नलिखित हैं:

public float calculateCoefficient(Collection collection) { 
    return collection.size() * something/somethingElse; 
} 

और दो अन्य विधियां जो इसे आमंत्रित करती हैं। अन्य विधियों में से एक LinkedList का उपयोग करता है क्योंकि यह इसके उद्देश्यों के लिए अधिक कुशल है, और दूसरा TreeSet का उपयोग करता है।

क्योंकि LinkedList और TreeSet दोनों Collection इंटरफ़ेस को लागू करते हैं, तो आप गुणांक गणना करने के लिए केवल एक विधि का उपयोग कर सकते हैं। अपने कोड को डुप्लिकेट करने की कोई आवश्यकता नहीं है।

और यहां "इंटरफ़ेस के लिए प्रोग्राम" आता है - आपको परवाह नहीं है कि size() विधि वास्तव में कैसे लागू की गई है, आपको पता है कि इसे संग्रह का आकार वापस करना चाहिए - यानी।यदि आप इसके बजाय LinkedList और विशेष रूप से TreeSet करने से Collection इंटरफ़ेस करने के लिए प्रोग्राम है। शायद एक किताब (उदाहरण के लिए "जावा में सोच रही थी") - - जहां अवधारणा विवरण में समझाया गया है

लेकिन मेरी सलाह एक पढ़ने मिल रहा है।

4

हर वस्तु एक उजागर इंटरफ़ेस है। एक संग्रह में Add, Remove, At आदि शामिल हैं। एक सॉकेट में Send, Receive, Close और इसी तरह हो सकता है।

हर वस्तु आप वास्तव में एक संदर्भ इन इंटरफेस की एक ठोस कार्यान्वयन है करने के लिए मिल सकता है।

इन बातों का

दोनों स्पष्ट सिर्फ अपनी प्रकाशित इंटरफेस रहे हैं ... लेकिन क्या कुछ हद तक कम स्पष्ट है,

आपका कोड एक वस्तु का कार्यान्वयन विवरण पर भरोसा नहीं करना चाहिए।

यदि आप इसे चरम पर ले जाते हैं, तो आप केवल Collection<T> के खिलाफ कोड और (ArrayList<T> के बजाय) पर कोड करेंगे। अधिक व्यावहारिक रूप से, बस सुनिश्चित करें कि आप अपने कोड को तोड़ने के बिना कुछ अवधारणात्मक रूप से समान रूप से स्वैप कर सकते हैं।

बाहर हैमर से Collection<T> उदाहरण: आप कुछ का एक संग्रह है, तो आप वास्तव में ArrayList<T> क्योंकि क्यों नहीं उपयोग कर रहे हैं। क्या आप वाकई कोड को तोड़ने के लिए है, कहते हैं, आप भविष्य में LinkedList<T> का उपयोग कर खत्म नहीं जा रहा है कर रहे हैं बनाना चाहिए।

+0

"प्रत्येक ऑब्जेक्ट में एक खुला इंटरफ़ेस है" - um। नहीं, यह नहीं है? आपके द्वारा सूचीबद्ध किए गए लोग, लेकिन किसी भी इंटरफेस को लागू नहीं करते हैं। – Nyerguds

2

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

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

8

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

वहाँ केवल सार वर्गों द्वारा परिभाषित इंटरफेस के मामले में वस्तुओं जोड़ तोड़ करने के लिए दो लाभ हैं:

  1. ग्राहक, वस्तुओं वे उपयोग के विशिष्ट प्रकार से अनजान रहते जब तक वस्तुओं इंटरफ़ेस का पालन के रूप में है कि ग्राहकों की उम्मीद है।
  2. ग्राहक इन वस्तुओं को लागू करने वाले वर्गों से अनजान रहते हैं। ग्राहकों को केवल इंटरफेस को परिभाषित अमूर्त वर्ग (एसएस) के बारे में पता है।

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

इस डिजाइन के आगे तर्क के लिए Factory Method pattern देखें।

स्रोत: "Design Patterns: Elements of Reusable Object-Oriented Software" जीओएफ द्वारा।

भी देखें: Factory Pattern. When to use factory methods?

18

एक इंटरफ़ेस संबंधित विधियों का संग्रह है, जिसमें केवल उन तरीकों के हस्ताक्षर शामिल हैं - वास्तविक कार्यान्वयन नहीं।
यदि कोई कक्षा इंटरफ़ेस लागू करती है (class Car implements IDrivable) इसे इंटरफ़ेस में परिभाषित सभी हस्ताक्षरों के लिए कोड प्रदान करना होगा।

मूल उदाहरण:
आपको कार और बाइक कक्षाएं हैं।

interface IDrivable 
{ 
    void accelerate(); 
    void brake();  
} 

class Car implements IDrivable 
{ 
    void accelerate() 
    { System.out.println("Vroom"); } 

    void brake() 
    { System.out.println("Queeeeek");} 
} 

class Bike implements IDrivable 
{ 
    void accelerate() 
    { System.out.println("Rattle, Rattle, ..."); } 

    void brake() 
    { System.out.println("..."); } 
} 

अब मान लेते हैं कि आप वस्तुओं का संग्रह डालते हैं, वह सब "drivable" (उनकी कक्षाओं सभी IDrivable को लागू कर रहे हैं: दोनों इंटरफेस IDrivable लागू):

List<IDrivable> vehicleList = new ArrayList<IDrivable>(); 
list.add(new Car()); 
list.add(new Car()); 
list.add(new Bike()); 
list.add(new Car()); 
list.add(new Bike()); 
list.add(new Bike()); 

तो अब आप उस संग्रह से अधिक लूप करना चाहते हैं, तो आप इस तथ्य पर भरोसा कर सकते accelerate() कि उस संग्रह में हर वस्तु को लागू करता है,:

for(IDrivable vehicle: vehicleList) 
{ 
    vehicle.accelerate(); //this could be a bike or a car, or anything that implements IDrivable 
} 

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

+2

यह उत्तर मेरे सिर के अंदर चला गया :) –

+0

खुद इंटरफेस का अच्छा स्पष्टीकरण, लेकिन यह वास्तव में सवाल का जवाब नहीं देता है। – Nyerguds

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