2010-03-23 15 views
15

से छिपाने, ओवरराइडिंग और कॉलिंग फ़ंक्शन मैं सी # सीख रहा हूं और मुझे निम्न समस्या का सामना करना पड़ा। आधार और व्युत्पन्न:सी # बेस क्लास

class MyBase 
{ 
    public void MyMethod() 
    { 
     Console.WriteLine("MyBase::MyMethod()"); 
    } 
} 


class MyDerived: MyBase 
{ 
    public void MyMethod() 
    { 
     Console.WriteLine("MyDerived::MyMethod()"); 
    } 
} 

अभी के लिए, virtual बिना और override प्रमुख शब्दों मैं दो वर्गों की है। जब मैं इसे संकलित करता हूं तो मुझे चेतावनी मिलती है (जो निश्चित रूप से अपेक्षित है) कि मैं MyBase कक्षा से छिपाने की कोशिश करता हूं।

मैं क्या करना चाहता हूं बेस क्लास से विधि को व्युत्पन्न कक्षा का उदाहरण रखने के लिए कॉल करना है। मैं इस तरह ऐसा करते हैं:

MyDerived myDerived = new MyDerived(); 
((MyBase)myDerived).MyMethod(); 

यह ठीक काम करता है जब मैं किसी भी virtual तरीकों में कीवर्ड निर्दिष्ट नहीं करते हैं, आदि। मैं कीवर्ड के संयोजन डालने की कोशिश की और मैं निम्नलिखित परिणाम मिल गया:

| MyBase::MyMethod | MyDerived::MyMethod | Result printed on the console | 
| -----------------|---------------------|-------------------------------| 
| -    | -     | MyBase::MyMethod()   | 
| -    | new     | MyBase::MyMethod()   | 
| virtual   | new     | MyBase::MyMethod()   | 
| virtual   | override   | MyDerived::MyMethod()   | 

मुझे आशा है कि तालिका आप के लिए स्पष्ट है।

  1. यह सही तरीका आधार वर्ग (((MyBase)myDerived).MyMethod();) से समारोह कॉल कर सकता: मैं दो प्रश्न है? मुझे base कीवर्ड के बारे में पता है, लेकिन इसे केवल व्युत्पन्न वर्ग के अंदर से ही बुलाया जा सकता है। क्या यह सही है?
  2. आखिरी मामले में क्यों (virtual और override संशोधक के साथ) विधि जिसे व्युत्पन्न वर्ग से बुलाया गया था? क्या आप कृपया इसे समझाएंगे?
+0

क्या आप कृपया जो चाहते हैं उस पर विस्तार से बता सकते हैं और क्या आपने अनुभव किया? मैं बस इतना कह सकता हूं कि "हाँ, यह सही दिखता है"। अंतिम प्रश्न के लिए आपको वास्तव में वर्चुअल विधि प्रेषण कार्य करने के तरीके पर पढ़ना चाहिए। जानकारी के लिए http://en.wikipedia.org/wiki/Virtual_method_table देखें। –

उत्तर

18

जब आप एक प्रकार है कि विधि ओवरराइड करता है का एक उदाहरण पर एक virtual विधि कॉल, ओवरराइड संस्करण हमेशा की तरह, कहा जाएगा, भले ही आप आधार वर्ग के लिए डाली।

विधि को ओवरराइड करने वाली कक्षा पर वर्चुअल विधि के आधार कार्यान्वयन को कॉल करने का एकमात्र तरीका व्युत्पन्न वर्ग (बेस क्लास नहीं) में दूसरी विधि बनाना है जो base कीवर्ड का उपयोग करके विधि को कॉल करता है।

सामान्य रूप से, ऐसा करने की आवश्यकता एक खराब एपीआई डिज़ाइन का संकेत है - यदि आपको लगता है कि आपको मूल संस्करण को कॉल करने की आवश्यकता होगी, तो व्युत्पन्न संस्करण का शायद एक अलग नाम होना चाहिए।

+2

+1 - अच्छी तरह से समझाया। डिजाइन चर्चा के लिए अतिरिक्त अंक। –

2

आप सही हैं - base केवल व्युत्पन्न कक्षा - Source के भीतर से ही बुलाया जा सकता है।

यह पृष्ठ बेस क्लास परिभाषा को ओवरराइड करने का एक उदाहरण भी देता है।

3

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

2
  1. आप 'में ठीक है, base किसी दिए गए उदाहरण के लिए बेस क्लास को संदर्भित करता है।
  2. शामिल तंत्र को बहुरूपता कहा जाता है: आपको चेतावनी के बिना बेहतर काम करना चाहिए। प्राकृतिक वस्तु उन्मुख अच्छे तरीके से आपके द्वारा उल्लिखित मामलों में से अंतिम है।

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

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