2009-12-18 9 views
7

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

+4

ऐसी कोई बात नहीं सी # में के रूप में कई विरासत नहीं है। आप केवल एक वर्ग से प्राप्त कर सकते हैं, लेकिन आप जितना चाहें उतने इंटरफेस को कार्यान्वित कर सकते हैं। – cwap

+3

ठीक है, इंटरफ़ेस को कार्यान्वित करना इंटरफेस के एकाधिक विरासत के रूप में देखा जा सकता है लेकिन कार्यान्वयन नहीं। यह एक भूरा क्षेत्र है। – dsimcha

+0

@cwap: इंटरफेस पर ध्यान केंद्रित करने वाला एक इंटरफ़ेस, कार्यान्वयन के बाद, मैं देख सकता हूं कि आप ऐसा क्यों सोचते हैं। मैंने अक्सर सुना है कि @dsimcha ने जिस तरह से टिप्पणी की थी, उसे समझाया, इसलिए मैं उलझन में नहीं था। –

उत्तर

10

एक अच्छा के लिए उदाहरण एक इंटरफेस एक भंडार पैटर्न है। आपका इंटरफ़ेस Get, GetAll, अपडेट, डिलीट इत्यादि जैसी विधियों को परिभाषित करेगा। कोई कार्यान्वयन नहीं, केवल हस्ताक्षर कार्य करें।

फिर, आप उस वर्ग के 'कंक्रीट' कार्यान्वयन को लिखने के लिए कह सकते हैं, MySQL। आपका यूआई केवल इंटरफ़ेस को संदर्भित करना चाहिए, हालांकि।

बाद में, यदि आप माइक्रोसॉफ्ट एसक्यूएल में बदलने का फैसला करते हैं, तो आप एक और ठोस कार्यान्वयन लिखते हैं, लेकिन आपके यूआई कोड को बदलने की जरूरत नहीं है (ज्यादा)।

एकाधिक विरासत सी # में मौजूद नहीं है, इस अर्थ में कि आप केवल एक 'कंक्रीट' वर्ग से उत्तराधिकारी हो सकते हैं; यद्यपि आप जितना चाहते हैं उतने इंटरफेस के रूप में आप उत्तराधिकारी (या 'कार्यान्वित') कर सकते हैं।

2

इंटरफेस बस अपने वस्तु, नहीं व्यवहार के लिए एक अनुबंध सार्वजनिक तत्वों की (जैसे गुण, तरीकों, घटनाओं) को परिभाषित के कुछ उदाहरण देते हैं।

interface IDog 
{ 
    void WagTail(); //notice no implementation 
    ISound Speak(); //notice no implementation 
} 

class Spaniel : IDog 
{ 
    public void WagTail() 
    { 
     Console.WriteLine("Shook my long, hairy tail"); 
    } 

    public ISound Speak() 
    { 
     return new BarkSound("yip"); 
    } 

} 

class Terrier : IDog 
{ 
    public void WagTail() 
    { 
     Console.WriteLine("Shook my short tail"); 
    } 

    public ISound Speak() 
    { 
     return new BarkSound("woof"); 
    } 
} 

अद्यतन

में "वास्तविक उदाहरण" मैं के साथ इंटरफेस का उपयोग करें: - यूनिट टेस्टिंग - जेनरिक (जैसे भंडार, गेटवे, सेटिंग)

interface Repository<T>{ 
    T Find(Predicate<T>); 
    List<T> ListAll(); 
} 

interface Gateway<T>{ 
    T GetFrom(IQuery query); 
    void AddToDatabase(IEntity entityItem); 
} 

interface Settings<T>{ 
    string Name { get; set; } 
    T Value { get; set; } 
    T Default { get; } 
} 
+1

बिल्कुल ठीक नहीं है कि मैं एक "असली उदाहरण" कहूंगा ... बस मेरी राय, लेकिन इस तरह के उदाहरण (कुत्तों, बिल्लियों, कारों और अन्य अवशोषण) ओओपी अवधारणाओं को समझने में मदद करने के लिए कुछ भी नहीं करते हैं। –

+0

क्षमा करें यह आपके लिए एक अच्छा उदाहरण नहीं था। मैं सार बेस कक्षा की तुलना में ध्यान केंद्रित करने की कोशिश कर रहा था। अद्यतन डेममार्क के बाद विचारों को देखें। –

1

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

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

इंटरफेस के उद्देश्य है कि आप परोक्ष मैं इंटरफ़ेस का एक उदाहरण में वर्ग है कि इंटरफ़ेस को लागू करता है डाल सकता है मैं:

interface I { 
    void doStuff(); 
} 

class Foo : I { 
    void doStuff() {} 

    void useAnI(I i) {} 
} 

var foo = new Foo(); 
I i = foo; // i is now a reference to the vtable pointer for I in foo. 
foo.useAnI(i); // Works. You've passed useAnI a Foo, which can be used as an I. 
+1

मुझे संदेह है कि एक सी # शुरुआती vtables के बारे में जानता है :-) –

+1

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

1
यहाँ

एक (जावा में है, लेकिन यह महत्वपूर्ण नहीं है, क्योंकि वे कर रहे हैं समान): अपने प्रोजेक्ट में मैं बना लिया है सरल अंतरफलक:

public interface Identifiable<T> { 
    public T getId(); 
} 

कौन सा एनोटेशन के कुछ प्रकार के लिए सरल प्रतिस्थापन है। अगला कदम: मैंने सभी इकाई वर्गों को इस इंटरफेस को कार्यान्वित कर दिया है।

तीसरा कदम कुछ वाक्य रचना-चीनी की तरह तरीकों लिखना है:

public <T> List<T> ids(List<? extends Identifiable<T> entities) { ... } 

यह एक उदाहरण मात्र था।

अधिक जटिल उदाहरण सत्यापन नियमों की तरह कुछ है:

public interface ValidationRule { 
    public boolean isValid(...); 
} 

तो, यह इंजन नियमों से लागू किया जाना आवश्यक है: क्या आप कुछ मान्यता इंजन (शायद आप द्वारा लिखित) और शासन के लिए एक सरल अंतरफलक है आप। और निश्चित रूप से कई विरासत होंगे क्योंकि आप निश्चित रूप से एक और नियम चाहते हैं।

0

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

मैं Head First Design Patterns की भी सिफारिश करता हूं। कोड उदाहरण जावा में हैं लेकिन आसानी से सी # में अनुवादित हैं, साथ ही वे आपको इंटरफेस और डिज़ाइन पैटर्न की वास्तविक शक्ति के साथ पेश करेंगे।

4

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

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

public interface IForce 
{ 
    void Update(Particle particle, GameTime gameTime); 
} 

यहां एक नमूना कार्यान्वयन है।

public class Spring : IForce 
{ 
    private Particle ThisParticle; 
    private Particle ThatParticle; 

    private float K; 

    public Spring(Particle thisParticle, Particle thatParticle, float k) 
    { 
     ThisParticle = thisParticle; 
     ThatParticle = thatParticle; 
    } 

    public void Update(Particle particle, GameTime gameTime) 
    {    
     float X = Vector3.Length(ThisParticle - ThatParticle); 

     ThisParticle.Forces.Add(K * X); 
    } 
} 

अपडेट फ़ंक्शन में समझने में आसान बनाने के लिए एक सरलीकृत वसंत बल अद्यतन है।

यह कुछ तरीकों से मदद करता है।

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

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

मैं कई अलग-अलग स्थितियों में हर दिन इंटरफेस का उपयोग करता हूं। वे शानदार हैं! [छद्म कोड]

interface Shape { 
    // shape methods like draw, move, getboundingrect, whatever. 
} 

interface Serializable { 
    // methods like read and write 
} 

class Circle : public Shape, public Serializable { 
    // TODO: implement Shape methods 
    // TODO: implement Serializable methods 
} 

// somewhere later 
{ 
    Circle circle; 
    // ... 
    deserializer.deserialize(circle); 
    // ... 
    graphicsurface.draw(circle); 
    // ... 
    serializer.serialize(circle); 
} 

विचार है कि अपने सर्किल वर्ग दो अलग इंटरफेस है कि बहुत अलग स्थितियों में किया जाता है लागू करता है:

+0

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

1

एकाधिक वंशानुक्रम एक वर्ग कई स्थितियों में प्रयोग करने योग्य होने होने के बारे में है।

+0

जो एकाधिक विरासत नहीं है, केवल कई इंटरफेस के कार्यान्वयन। सी # एकाधिक विरासत का समर्थन नहीं करता है, साथ ही यह नहीं होना चाहिए। –

+1

यह सी # .. – Fozi

1

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

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

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

उदाहरण के लिए, मैं एक प्रोग्राम बना रहा हूं जो उपयोगकर्ता को 4 अलग-अलग प्रकार के मानचित्र उत्पन्न करने की अनुमति देता है। इसके लिए, मैंने 4 अलग-अलग प्रकार के जनरेटर वर्ग बनाए हैं। वे सभी 'IGenerator' इंटरफ़ेस को लागू हालांकि:

public interface IGenerator { 
    public void generateNow(int period); 
} 

कौन सा उन्हें बताता है कम से कम एक "सार्वजनिक generateNow (पूर्णांक अवधि)" समारोह को परिभाषित करने के।

मैं जो भी जेनरेटर मूल रूप से था, उसे "आईजेनरेटर" में डालने के बाद मैं इसे "जेनरनेट (4)" कह सकता हूं। मुझे यह सुनिश्चित करने की ज़रूरत नहीं होगी कि मैं किस तरह का जेनरेटर लौटा, जिसका अनिवार्य रूप से मतलब है, अब "क्लास 1 का चरणीय उदाहरण", "क्लास 2 का चरणीय उदाहरण" इत्यादि।

+0

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

3

नोट: इंटरफ़ेस का उपयोग किसी भी कीमत पर differents कक्षाओं से विधियों या घटनाओं आदि को प्रतिबंधित और एक्सेस करने के लिए किया जाता है, इसका मतलब है कि हम किसी भी कक्षा के अंदर कई और तरीकों को परिभाषित कर सकते हैं, लेकिन जब हम इंटरफेस के माध्यम से तरीकों को बुला रहे हैं तो हम केवल अन्य चाहते हैं प्रतिबंधित विधियां नीचे दिए गए कार्यक्रम में उपयोगकर्ता 1 का उपयोग कर सकते हैं & दोनों लिखें लेकिन उपयोगकर्ता 2 लिख और निष्पादित कर सकते हैं। ......... नीचे इस कार्यक्रम देखें

namespace ExplConsole 
{ 
    class Program 
    { 
     static void Main() 
     { 
      System.Console.WriteLine("Permission for User1"); 
      User1 usr1 = new Test(); // Create instance. 
      usr1.Read(); // Call method on interface. 
      usr1.Write(); 
      System.Console.WriteLine("Permission for User2"); 
      User2 usr2 = new Test(); 
      usr2.Write(); 
      usr2.Execute(); 
      System.Console.ReadKey(); 
     } 
    } 
    interface User1 
    { 
     void Read(); 
     void Write(); 
    } 
    interface User2 
    { 
     void Write(); 
     void Execute(); 
    } 
    class Test : NewTest,User1, User2 
    { 
     public void Read() 
     { 
      Console.WriteLine("Read"); 
     } 
     public void Write() 
     { 
      Console.WriteLine("Write"); 
     } 
    } 
    class NewTest 
    { 
     public void Execute() 
     { 
      Console.WriteLine("Execute"); 
     } 
    } 
} 

आउटपुट:

Permission for User1 
    Read 
    Write 
    Permission for User2 
    Write 
    Execute 
संबंधित मुद्दे