2008-11-11 15 views
9

codeplex में एएसपी.नेट एमवीसी स्रोत कोड ब्राउज़ करते समय, मुझे लगता है कि क्लास स्पष्ट रूप से कार्यान्वित इंटरफ़ेस को कक्षा में रखना आम है। स्पष्ट रूप से कार्यान्वित विधि/संपत्ति तब एक ही नाम के साथ एक और "संरक्षित आभासी" विधि/संपत्ति का आह्वान करती है।संरक्षित विधि को आमंत्रित करने के लिए स्पष्ट इंटरफ़ेस कार्यान्वयन का उपयोग क्यों करें?

उदाहरण के लिए,

public class MvcHandler : IHttpHandler, IRequiresSessionState 
{ 
    protected virtual bool IsReusable 
    { 
     get 
     { 
      return false; 
     } 
    } 

    bool IHttpHandler.IsReusable 
    { 
     get 
     { 
      return IsReusable; 
     } 
    } 
} 

मैं अब यकीन है कि प्रोग्रामिंग इस तरह के लाभ क्या कर रहा हूँ। मेरे लिए, मैं सिर्फ इंटरफ़ेस IHttpHandler को निहित रूप से लागू करना पसंद करता हूं।

मैं लेखक लगता है कि बस नहीं करना चाहती MvcHandler एक सार्वजनिक संपत्ति IsResuable है। संपत्ति IsReusable का उपयोग केवल तभी किया जा सकता है जब MvcHandler का उदाहरण IHttpHandler के रूप में माना जाता है। फिर भी, मुझे यकीन नहीं है कि लेखक इस तरह से क्यों है।

कोई भी इंटरफ़ेस कार्यान्वयन की इस शैली के बारे में अधिक लाभ जानता है?

+2

यह मजाकिया है, एमवीसी स्रोत को आपके प्रारंभिक पोस्ट के ठीक उसी दिन 3 साल बाद पढ़ना, मेरे पास बिल्कुल वही सवाल था। – ScottS

उत्तर

13

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

(ICloneable सादगी के लिए चुना:

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

class Foo : ICloneable 
{ 
    public Foo Clone() { return CloneCore(); } 
    object ICloneable.Clone() { return CloneCore(); } 
    protected virtual Foo CloneCore() { ... } 
} 

class Bar : Foo 
{ 
    protected override Foo CloneCore() { ... } 
    public new Bar Clone() { return (Bar)CloneCore(); } 
} 

एक छोटी उदाहरण में दिखाने के लिए) अगर हम एक सार्वजनिक आभासी विधि का इस्तेमाल किया था कठिन है, हम नहीं सक्षम हो - .. एक बेहतर उदाहरण DbCommand आदि, जो ऐसा करने जैसी बातों होता है override पर और यू आधार वर्ग में से new, आप दोनों क्या करने की अनुमति नहीं है के रूप में:

class A 
{ 
    public virtual A SomeMethod() { ... } 
} 
class B : A 
{ 
    public override A SomeMethod() { ... } 
    //Error 1 Type 'B' already defines a member called 'SomeMethod' with the same parameter types 
    public new B SomeMethod() { ... } 
} 

संरक्षित आभासी दृष्टिकोण का उपयोग करना, किसी भी उपयोग:

  • Foo.Clone()
  • बार। क्लोन()
  • ICloneable.Clone()

सभी concret के लिए सही CloneCore() कार्यान्वयन का उपयोग ई टाइप।

+0

+1 पुरानी लेकिन गुडई के लिए +1, धन्यवाद। –

1
  1. जब कोई सदस्य स्पष्ट रूप से कार्यान्वित किया जाता है, तो इसे क्लास इंस्टेंस के माध्यम से एक्सेस नहीं किया जा सकता है, लेकिन केवल इंटरफ़ेस के उदाहरण के माध्यम से। संदर्भ: Explicit Interface Implementation Tutorial
  2. मेरे अनुभव के रूप में यदि इंटरफ़ेस कार्यान्वयनकर्ता एक इंटरफ़ेस को स्पष्ट रूप से कार्यान्वित करता है तो उसे इंटरफ़ेस से कोई विधि छोड़ने के बाद संकलक त्रुटि प्राप्त होगी, जबकि वह सूचित नहीं करेगा कि वह इसे लागू करता है और विधि कोड में रहेगी।

कारण 1 के लिए नमूना: एक वर्ग स्पष्ट रूप IFoo.Bar लागू करता है, और एक व्युत्पन्न वर्ग IFoo.Bar की जरूरत है कुछ अलग करना

public interface IFoo 
{ 
    void method1(); 
    void method2(); 
} 

public class Foo : IFoo 
{ 
    // you can't declare explicit implemented method as public 
    void IFoo.method1() 
    { 
    } 

    public void method2() 
    { 
    } 

    private void test() 
    { 
     var foo = new Foo(); 
     foo.method1(); //ERROR: not accessible because foo is object instance 
     method1(); //ERROR: not accessible because foo is object instance 
     foo.method2(); //OK 
     method2(); //OK 

     IFoo ifoo = new Foo(); 
     ifoo.method1(); //OK, because ifoo declared as interface 
     ifoo.method2(); //OK 
    } 
} 
+0

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

2

है, वहाँ व्युत्पन्न वर्ग आधार कॉल करने के लिए कोई रास्ता नहीं होगा उस विधि के क्लास कार्यान्वयन। एक व्युत्पन्न वर्ग जो IFoo.Bar को पुन: कार्यान्वित नहीं करता है, ((IFoo)this).Bar() के माध्यम से बेस-क्लास कार्यान्वयन को कॉल कर सकता है, लेकिन यदि व्युत्पन्न कक्षा IFoo.Bar (जैसा कि इसे अपने व्यवहार को बदलने के लिए) को दोबारा लागू किया गया है, तो उपर्युक्त कॉल व्युत्पन्न पर जायेगा बेस-क्लास कार्यान्वयन के बजाए -क्लास पुन: कार्यान्वयन। यहां तक ​​कि ((IFoo)(BaseType)this).bar भी मदद नहीं करेगा, क्योंकि किसी इंटरफ़ेस प्रकार का संदर्भ डालने से संदर्भ के प्रकार (उदाहरण के उदाहरण के विपरीत) के बारे में किसी भी जानकारी को त्याग दिया जाएगा।

एक स्पष्ट इंटरफ़ेस कार्यान्वयन होने के अलावा कुछ भी नहीं है, लेकिन एक संरक्षित विधि को कॉल करें, इस समस्या से बचाता है, क्योंकि व्युत्पन्न वर्ग वर्चुअल विधि को ओवरराइड करके इंटरफ़ेस विधि के व्यवहार को बदल सकता है, जबकि आधार कार्यान्वयन को कॉल करने की क्षमता को बनाए रखने की क्षमता को बनाए रखने के दौरान फिट। आईएमएचओ, सी # में एक स्पष्ट इंटरफ़ेस कार्यान्वयन एक सीएलएस-अनुपालन नाम के साथ वर्चुअल विधि उत्पन्न करना चाहिए था, इसलिए सी # # में लिखे गए किसी व्यक्ति ने कक्षा को व्युत्पन्न किया जो IFoo.Bar स्पष्ट रूप से लागू किया गया था override void IFoo.Bar, और किसी अन्य भाषा में लिखने वाला कोई व्यक्ति कह सकता है, उदा। Overrides Sub Explicit_IFoo_Bar(); चूंकि कोई भी व्युत्पन्न वर्ग IFoo.Bar को फिर से कार्यान्वित कर सकता है, और चूंकि किसी भी व्युत्पन्न वर्ग जो IFoo.Bar को पुन: कार्यान्वित नहीं करता है, इसे स्वयं ही कॉल कर सकता है, मुझे नहीं लगता कि स्पष्ट कार्यान्वयन को सील करने का कोई उपयोगी उद्देश्य है।

संयोग से, vb.net में, सामान्य पैटर्न केवल Protected Overridable Sub IFoo_Bar() Implements IFoo.Bar होगा, बिना किसी अलग वर्चुअल विधि की आवश्यकता के।

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