2010-06-01 10 views
25

मैं निम्नलिखित वर्गों आ रही हैं:"ओवरराइड" सी # में बनाम 'नई' के बारे में उलझन में

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    public new virtual void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 

class Der2 : Der1 
{ 
    public override void Print() 
    { 
     Console.WriteLine("Der2"); 
    } 
} 

यह मेरा मुख्य विधि है:

Base b = new Der2(); 
Der1 d1 = new Der2(); 
Der2 d2 = new Der2(); 

b.Print(); 
d1.Print(); 
d2.Print(); 

उत्पादन, Base है Der2, Der2

जहां तक ​​मुझे पता है, ओवरराइड पिछली विधि को चलाने की अनुमति नहीं देगा, भले ही पॉइंटर उन्हें इंगित कर रहा हो। तो पहली पंक्ति Der2 आउटपुट भी होनी चाहिए। हालांकि Base बाहर आया।

यह कैसे संभव है? ओवरराइड कैसे काम नहीं करता था?

+0

सच एक अद्भुत उदाहरण ... केवल चाल यहाँ है: - शुरू में, आधार के की विधि, "डेर -1" की आभासी विधि से छिपा हुआ था तो "की ओवर-द सवारी विधि डेर -2 "लागू नहीं किया जा सका। इस प्रकार, हमें आधार का मूल्य मिला। – Kings

उत्तर

27

आपने कभी Print() के Base संस्करण को कभी भी ओवरराइड नहीं किया है। आपने इसे Der1 में केवल एक अलग वर्चुअल विधि (उसी नाम से) के साथ छुपाया है।

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

Der2 में जब आप Print ओवरराइड आप वास्तव में 'नए' संस्करण है कि आप Der1 में घोषित अधिभावी कर रहे हैं - नहीं संस्करण Base है। एरिक लिपर्ट के पास excellent answer है जो थोड़ा अलग प्रश्न है जो आपको सी # भाषा में वर्चुअल विधियों का इलाज करने के तरीके के बारे में बता सकता है।

अपने उदाहरण में, जब आप Print कहते हैं, आप इसे पहले मामले में प्रकार Base के एक संदर्भ के माध्यम से बुला रहे हैं - तो छिपा (लेकिन ओवरराइड नहीं) Print के संस्करण कहा जाता है। अन्य दो कॉल Der1 के कार्यान्वयन के लिए भेजी जाती हैं, क्योंकि इस मामले में, आपने वास्तव में विधि को ओवरराइड कर दिया है।

आप MSDN documentation of new and override में इसके बारे में अधिक पढ़ सकते हैं।

आप Der1 साथ क्या करने का इरादा हो सकता है क्या (के रूप में आप Der2 के साथ किया था) override कीवर्ड का उपयोग करने के लिए है:

class Base 
{ 
    public virtual void Print() 
    { 
     Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    // omitting 'new' and using override here will override Base 
    public override void Print() 
    { 
     Console.WriteLine("Der1"); 
    } 
} 
+0

यही वह है जो उसने Der2 के साथ किया था। – GalacticCowboy

+0

@ गैलेक्टिककॉबॉय - वास्तव में, यह मेरा मुद्दा था। शायद यह संभवतः Der1 में भी क्या था, लेकिन किसी भी तरह 'ओवरराइड' की बजाय 'नया' कीवर्ड फिसल गया था। मैं इसे और अधिक स्पष्ट करने के लिए अपनी पोस्ट अपडेट करूंगा। – LBushkin

+0

धन्यवाद। एक अद्भुत जवाब, मैं पूरी तरह से समझ गया कि यह अब कैसे काम करता है। – iTayb

5

यह क्योंकि Der1नहीं ओवरराइडPrint, यह एक साथ यह बदल देता करता है ब्रांड नई विधि जो समान नाम होती है (यह new कीवर्ड के उपयोग के कारण होती है)। इसलिए, जब ऑब्जेक्ट Base पर डाला जाता है तो यह PrintBase में कॉल करता है; कॉल करने के लिए कोई ओवरराइड नहीं है ..

1

override पिछले विधि तो Base के Print() के सबसे ओवरराइड verion का स्थान ले लेगा, लेकिन के रूप में अपने Der1 वर्ग Print() पर हावी नहीं होता (यह छाया, एक वीबी-वाद का उपयोग करने के लिए), कहा जाता है, जो करने के लिए होता यह संस्करण होना चाहिए जो

0

जैसा कि सभी ने कहा है कि Der1Print() को ओवरराइड करने के बजाय बदल रहा है। इसे क्रिया में देखने के लिए आप d1 और d2 से Base पर आधारित हो सकते हैं और फिर प्रिंट विधि को कॉल कर सकते हैं। इसके बाद यह Base लौटाएगा।

((Base)d2).Print(); //Base 
संबंधित मुद्दे