2009-09-09 11 views
134

सोच क्या अंतर निम्नलिखित के बीच है:अंतर ओवरराइड

केस 1: बेस कक्षा

public void DoIt(); 

केस 1: विरासत में प्राप्त वर्ग

public new void DoIt(); 

केस 2: बेस कक्षा

public virtual void DoIt(); 

केस 2: विरासत में प्राप्त वर्ग

public override void DoIt(); 

दोनों मामले 1 और 2 परीक्षण मैं चलाने के आधार पर एक ही प्रभाव दिखाई देते हैं। क्या कोई अंतर है, या पसंदीदा तरीका है?

+2

http://stackoverflow.com/questions/159978/c-keyword-usage-virtualoverride-vs-new –

उत्तर

170

ओवरराइड संशोधक आभासी तरीकों पर इस्तेमाल किया जा सकता और सार तरीकों पर इस्तेमाल किया जाना चाहिए। यह को संकलित करने के लिए अंतिम विधि विधि के कार्यान्वयन का उपयोग करने के लिए इंगित करता है। यहां तक ​​कि विधि को के संदर्भ में बेस क्लास के संदर्भ में कहा जाता है, तो यह कार्यान्वयन को ओवरराइड करने का उपयोग करेगा।

public class Base 
{ 
    public virtual void DoIt() 
    { 
    } 
} 

public class Derived : Base 
{ 
    public override void DoIt() 
    { 
    } 
} 

Base b = new Derived(); 
b.DoIt();      // Calls Derived.DoIt 

Derived.DoIt कॉल करेंगे कि अगर ओवरराइड करता है Base.DoIt

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

public class Base 
{ 
    public virtual void DoIt() 
    { 
    } 
} 

public class Derived : Base 
{ 
    public new void DoIt() 
    { 
    } 
} 

Base b = new Derived(); 
Derived d = new Derived(); 

b.DoIt();      // Calls Base.DoIt 
d.DoIt();      // Calls Derived.DoIt 

पहले Base.DoIt तो Derived.DoIt फोन करेंगे,। वे आधार विधि को ओवरराइड करने वाली व्युत्पन्न विधि के बजाय प्रभावी रूप से दो पूरी तरह अलग विधियों के समान होते हैं।

स्रोत: Microsoft blog

+4

सहित कई सवाल, की डुप्लीकेट 'यह संकलक एक के अंतिम परिभाषित कार्यान्वयन का उपयोग करने के लिए इंगित करता है method'। एक विधि के अंतिम परिभाषित कार्यान्वयन कैसे प्राप्त कर सकते हैं ?? – AminM

+5

एक ठोस वर्ग से शुरू करें, जांचें कि क्या इसमें ब्याज की विधि का कार्यान्वयन है। यदि ऐसा होता है, तो आप कर चुके हैं। यदि ऐसा नहीं होता है, तो विरासत पदानुक्रम में एक कदम ऊपर जाएं, यानी, जांच करें कि सुपर क्लास में ब्याज की विधि है या नहीं। तब तक जारी रखें जब तक आपको ब्याज की विधि नहीं मिल जाती। – csoltenborn

7

निम्न प्रयास करें: (case1)

((BaseClass)(new InheritedClass())).DoIt() 

संपादित करें: आभासी + ओवरराइड जबकि नए सिर्फ एक ही नाम के साथ नई विधि बनाने के लिए, (ताकि ओवरराइड वास्तव में आभासी तरीकों ओवरराइड करता है) रनटाइम पर हल कर रहे हैं, और पुराने खाल , यह संकलन समय पर हल किया गया है -> आपका कंपाइलर

13

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

149

आभासी: इंगित करता है कि एक विधि एक उत्तराधिकारी

ओवरराइड द्वारा ओवरराइड किया जा सकता है: एक आधार वर्ग में एक आभासी विधि की कार्यक्षमता को ओवरराइड करता है, विभिन्न कार्यक्षमता प्रदान करते हैं।

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

जब आप कोई विधि छुपाते हैं, तो भी आप बेस क्लास को कास्टिंग करके मूल विधि तक पहुंच सकते हैं। यह कुछ परिदृश्यों में उपयोगी है, लेकिन खतरनाक है।

+0

एक विधि कास्टिंग क्यों कर रहा है जो आधार विधि को खतरनाक करता है? या आप यह कह रहे हैं कि सामान्य रूप से कास्टिंग खतरनाक है? – Mark

+1

@ मार्क - एक कॉलर कार्यान्वयन से अवगत नहीं हो सकता है, जिससे आकस्मिक दुरुपयोग हो सकता है। –

3

दो मामलों के बीच अंतर यह है कि 1 स्थिति में, बेस DoIt विधि ओवरराइड नहीं होती है, बस छिपी हुई है। इसका अर्थ यह है कि चर के प्रकार के आधार पर निर्भर करता है कि किस विधि को बुलाया जाएगा। उदाहरण के लिए:

BaseClass instance1 = new SubClass(); 
instance1.DoIt(); // Calls base class DoIt method 

SubClass instance2 = new SubClass(); 
instance2.DoIt(); // Calls sub class DoIt method 

यह वास्तव में भ्रमित हो सकता है और परिणामस्वरूप गैर अपेक्षित व्यवहार में परिणाम हो सकता है और यदि संभव हो तो इससे बचा जाना चाहिए। तो पसंदीदा तरीका 2 होगा।

3

यदि आप विरासत वर्ग की DoIt() विधि को कॉल करते हैं तो टाइप 1 के मामले में टाइप क्लास के रूप में घोषित किया जाता है, तो आपको बेस क्लास की कार्रवाई भी दिखाई देगी।

/* Results 
Class1 
Base1 
Class2 
Class2 
*/ 
public abstract class Base1 
{ 
    public void DoIt() { Console.WriteLine("Base1"); } 
} 
public class Class1 : Base1 
{ 
    public new void DoIt() { Console.WriteLine("Class1"); } 
} 
public abstract class Base2 
{ 
    public virtual void DoIt() { Console.WriteLine("Base2"); } 
} 
public class Class2 : Base2 
{ 
    public override void DoIt() { Console.WriteLine("Class2"); } 
} 
static void Main(string[] args) 
{ 
    var c1 = new Class1(); 
    c1.DoIt(); 
    ((Base1)c1).DoIt(); 

    var c2 = new Class2(); 
    c2.DoIt(); 
    ((Base2)c2).DoIt(); 
    Console.Read(); 
} 
+0

जब आप अपना कोड – Learner

+0

आज़माते हैं तो आप इसे अमान्य टोकन के रूप में दिखाते हैं। क्या आप जो चेतावनी या त्रुटि प्राप्त कर रहे हैं उसे पोस्ट कर सकते हैं। जब मैंने मूल रूप से इसे पोस्ट किया था तो यह कोड ठीक काम करता था। –

+0

यह सब आपके एंट्री पॉइंट क्लास (प्रोग्राम) के भीतर चिपकाया जाना चाहिए। इसे इस साइट पर बेहतर स्वरूपण की अनुमति देने के लिए हटा दिया गया था। –

1

यदि कीवर्ड override तो इसकी ओवरराइड माता पिता विधि प्राप्त कक्षा में प्रयोग किया जाता है।

यदि कीवर्ड new का उपयोग कक्षा में प्राप्त किया जाता है तो मूल विधि द्वारा छिपी हुई विधि प्राप्त करें।

BaseClass bc = new BaseClass(); 

bc.DoIt(); 

DerivedClass dc = new DerivedClass(); 

dc.ShowIt(); 

इस exmample में, छदाम कहा जाता है वह यह है कि एक आप कहा जा करने की उम्मीद:

0

कार्यात्मक अंतर इन परीक्षणों में शो नहीं होगा।

आदेश अंतर आप ऐसा करते हैं करने के लिए है देखने के लिए:

BaseClass obj = new DerivedClass(); 

obj.DoIt(); 

आपको लगता है कि परीक्षण उस मामले 1 (आप इसे परिभाषित है) में, BaseClass में DoIt() कहा जाता है चलाते हैं तो आप देखेंगे, यदि 2 (जैसा कि आपने इसे परिभाषित किया है) में DoIt()DerivedClass में कहा जाता है।

0

मैं एक ही सवाल था और यह वास्तव में भ्रामक है, आप पर विचार करना चाहिए कि ओवरराइड और नई कीवर्ड प्रकार आधार वर्ग और व्युत्पन्न वर्ग का मूल्य की वस्तुओं के साथ काम कर ही।इस मामले में केवल आप ओवरराइड और नए का असर दिखाई देगा: तो अगर आप class A और B, A से B inherits है, तो आप एक वस्तु इस तरह का दृष्टांत:

A a = new B(); 

अब बुला तरीकों पर ले जाएगा इसकी स्थिति पर विचार करें। ओवरराइड: इसका अर्थ यह है कि यह विधि के कार्य को बढ़ाता है, फिर यह व्युत्पन्न वर्ग में विधि का उपयोग करता है, जबकि नया व्युत्पन्न वर्ग में विधि को छिपाने के लिए संकलक को बताएं और इसके बजाय बेस क्लास में विधि का उपयोग करें।

https://msdn.microsoft.com/EN-US/library/ms173153%28v=VS.140,d=hv.2%29.aspx?f=255&MSPPError=-2147217396

1

मन दोनों खोजशब्दों कि वे एक दूसरे के विपरीत हैं में रखना मेरे रास्ते: यहाँ है कि इस विषय के लिए एक बहुत अच्छा दृश्य है।

override: virtual कीवर्ड को विधि को ओवरराइड करने के लिए परिभाषित किया जाना चाहिए। override कीवर्ड का उपयोग करने वाली विधि, संदर्भ प्रकार (बेस क्लास या व्युत्पन्न कक्षा का संदर्भ) चाहे बेस बेस के साथ तत्काल हो, बेस बेस की विधि चलती है। अन्यथा, व्युत्पन्न वर्ग की विधि चलती है।

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

class A 
{ 
    public string Foo() 
    { 
     return "A"; 
    } 

    public virtual string Test() 
    { 
     return "base test"; 
    } 
} 

class B: A 
{ 
    public new string Foo() 
    { 
     return "B"; 
    } 
} 

class C: B 
{ 
    public string Foo() 
    { 
     return "C"; 
    } 

    public override string Test() { 
     return "derived test"; 
    } 
} 

मुख्य में कॉल:

A AClass = new B(); 
Console.WriteLine(AClass.Foo()); 
B BClass = new B(); 
Console.WriteLine(BClass.Foo()); 
B BClassWithC = new C(); 
Console.WriteLine(BClassWithC.Foo()); 

Console.WriteLine(AClass.Test()); 
Console.WriteLine(BClassWithC.Test()); 

आउटपुट:

A 
B 
B 
base test 
derived test 
1

नीचे दिए गए लेख vb.net में है, लेकिन मुझे लगता है कि ओवरराइड नए बनाम के बारे में स्पष्टीकरण समझ बहुत आसान है।

https://www.codeproject.com/articles/17477/the-dark-shadow-of-overrides

लेख में कुछ बिंदु पर, वहाँ इस वाक्य है:

सामान्य तौर पर, छाया, समारोह प्रकार के साथ जुड़े शुरू हो जाती है मान लिया गया है, जबकि ओवरराइड मान लिया वस्तु कार्यान्वयन है मार डाला।

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

-1

उन सभी में से, नया सबसे भ्रमित है। प्रयोग के माध्यम से, नया कीवर्ड डेवलपर्स को स्पष्ट रूप से प्रकार को परिभाषित करके बेस क्लास कार्यान्वयन के साथ विरासत वर्ग कार्यान्वयन को ओवरराइड करने का विकल्प प्रदान करना है। यह दूसरी तरफ सोचने की तरह है।

नीचे दिए गए उदाहरण में, परिणाम "व्युत्पन्न परिणाम" वापस लौटाएगा जब तक कि बेस को बेसक्लास परीक्षण के रूप में स्पष्ट रूप से परिभाषित नहीं किया जाता है, केवल तभी "बेस परिणाम" वापस कर दिया जाएगा।

class Program 
{ 
    static void Main(string[] args) 
    { 
     var test = new DerivedClass(); 
     var result = test.DoSomething(); 
    } 
} 

class BaseClass 
{ 
    public virtual string DoSomething() 
    { 
     return "Base result"; 
    } 
} 

class DerivedClass : BaseClass 
{ 
    public new string DoSomething() 
    { 
     return "Derived result"; 
    } 
} 
+0

फ़ीड न करें अगर आप ऑब्जेक्ट करते हैं तो अपनी टिप्पणी जोड़ें। हिट और रन इतनी डरावनी है। – usefulBee

0

पहले मामले में यह व्युत्पन्न कक्षा DoIt() विधि को कॉल करेगा क्योंकि नया कीवर्ड बेस क्लास DoIt() विधि को छुपाता है।

दूसरे मामले में यह छदाम ओवरराइड फोन करेगा()

public class A 
{ 
    public virtual void DoIt() 
    { 
     Console.WriteLine("A::DoIt()"); 
    } 
} 

public class B : A 
{ 
    new public void DoIt() 
    { 
     Console.WriteLine("B::DoIt()"); 
    } 
} 

public class C : A 
{ 
    public override void DoIt() 
    { 
     Console.WriteLine("C::DoIt()"); 
    } 
} 

पर इन कक्षाओं

A instanceA = new A(); 

    B instanceB = new B(); 
    C instanceC = new C(); 

    instanceA.DoIt(); //A::DoIt() 
    instanceB.DoIt(); //B::DoIt() 
    instanceC.DoIt(); //B::DoIt() 

सब कुछ ऊपर से आशा की जाती है के कहने बना सकते हैं। ExampleA और exampleC को exampleA सेट करने दें और DoIt() विधि को कॉल करें और परिणाम जांचें।

instanceA = instanceB; 
    instanceA.DoIt(); //A::DoIt() calls DoIt method in class A 

    instanceA = instanceC; 
    instanceA.DoIt();//C::DoIt() calls DoIt method in class C because it was overriden in class C 
संबंधित मुद्दे