2011-11-15 12 views
7

पर काम नहीं कर रहे पॉलीमोर्फिक तरीके मैं बस एक बहुत ही रोचक समस्या पर ठोकर खाई। निम्नलिखित कोड दे:सी # 4

using System; 

class Program 
{ 
    class A { } 
    class B : A { } 

    private static void MyMethod(A a) /* first method */ 
    { 
     Console.WriteLine("A"); ; 
    } 

    private static void MyMethod(B b) /* second method */ 
    { 
     Console.WriteLine("B"); 
    } 

    static void Main(string[] args) 
    { 
     var a = new A(); 
     // Call first method 
     MyMethod(a); 

     A b = new B(); 
     // Should call the second method 
     MyMethod(b); 

     Console.ReadLine(); 
    } 
} 

मैं उम्मीद होती है कि दूसरी विधि क्योंकि चर के क्रम प्रकार बी क्यों कोड पहली विधि के बजाय कॉल कोई भी विचार है बुलाया जाएगा?

धन्यवाद, Tibi

कुछ स्पष्टीकरण: बहुरूपता कई रूपों जो करने के लिए आप जहां प्रणाली की घोषणा कुछ भी नहीं है का मतलब है।

विधि अधिभार पॉलिमॉर्फिज्म का एक रूप है, ad-hoc polymorphism।

जिस तरह से पॉलिमॉर्फिज्म सामान्य रूप से देर से बाध्यकारी का उपयोग करके लागू किया जाता है।

गतिशील इस समस्या के लिए कामकाज है।

तथ्य यह है कि यह सी # (या जावा) में काम नहीं कर रहा है, यह एक डिज़ाइन निर्णय है जिसे मैं समझना चाहता हूं कि क्यों बनाया गया था, और कोई भी जवाब इस प्रश्न का उत्तर नहीं दे रहा है।

/Tibi

+4

यह बहुरूपता नहीं है, आपके पास एक ही विधि के दो अधिभारित उदाहरण हैं, प्रत्येक पैरामीटर के रूप में विभिन्न प्रकार लेते हैं। फिर आप ए के रूप में "बी" घोषित करते हैं। कंपाइलर आपको ऐसा करने देता है क्योंकि बी को ए – Maess

उत्तर

6

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

static void Main(string[] args) 
{ 
    dynamic d = new A(); 
    // Call first method 
    MyMethod(d); 

    d = new B(); 
    // Call the second method 
    MyMethod(d); 

    Console.ReadLine(); 
} 
+0

मैंने इसके बारे में नहीं सोचा था! धन्यवाद। – Tibi

+0

मुझे वास्तव में पता नहीं था कि 'गतिशील' कीवर्ड रनटाइम पर हल करने के लिए ओवरलोडेड विधियों को कॉल करता है, यह जानना आसान है। मैं इस तरह के देर से बाध्यकारी के साथ संभावित प्रदर्शन मुद्दों के रूप में उत्सुक हूँ। –

+1

मुझे लगता है कि आप पहली बार कुछ प्रदर्शन हिट करेंगे जब आप इसे नए पैरामीटर प्रकार के साथ कॉल करेंगे क्योंकि इसे हल करने की आवश्यकता है, लेकिन फिर डीएलआर द्वारा कैश किया जाता है। – Tibi

14

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

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

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

MyMethod((B)b); 
+0

वास्तव में प्राप्त होता है। जावा में भी यही बात होती है। अपेक्षित् व्यवहार। – EdH

+0

एक और जटिल परिस्थिति में कास्टिंग सिर्फ कोड बदसूरत बना देगा। वैसे भी, मैं लिंकर को पैरामीटर के प्रकार की देखभाल करने और इसके बजाय देर से बाध्यकारी उपयोग करने की अपेक्षा करता हूं। – Tibi

+1

यदि आप इसे इस तरह से व्यवहार करना चाहते हैं तो आपको 'ए' पर 'DoSomething' उप' रखना चाहिए, और इसे 'बी' में ओवरराइड करना चाहिए। फिर जब आप 'b.DoSomething()' को कॉल करते हैं तो यह वास्तविक प्रकार के आधार पर सही एक को चुन देगा। –

0

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

+0

मैं समझता हूं कि यह वास्तव में क्या करता है, मुझे समझ में नहीं आता क्यों। – Tibi

+1

संकलन समय पर विधि कॉल का समाधान किया जाता है। ('गतिशील 'प्रकार' विधियों को बाहर रखा गया) यही कारण है कि। – recursive

+0

रनटाइम पर पॉलीमोर्फिक विधियों का समाधान किया जाता है। – Tibi