C # में छायांकन और ओवरराइडिंग के बीच अंतर?


100

C # में एक विधि को छायांकित करने और ओवरराइड करने में क्या अंतर है?

जवाबों:


152

अच्छी तरह से विरासत ...

मान लीजिए कि आपके पास यह कक्षाएं हैं:

class A {
   public int Foo(){ return 5;}
   public virtual int Bar(){return 5;}
}
class B : A{
   public new int Foo() { return 1;}     //shadow
   public override int Bar() {return 1;} //override
}

तब जब आप यह कहते हैं:

A clA = new A();
B clB = new B();

Console.WriteLine(clA.Foo()); // output 5
Console.WriteLine(clA.Bar()); // output 5
Console.WriteLine(clB.Foo()); // output 1
Console.WriteLine(clB.Bar()); // output 1

//now let's cast B to an A class
Console.WriteLine(((A)clB).Foo()); // output 5 <<<-- shadow
Console.WriteLine(((A)clB).Bar()); // output 1

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

यहां कोड चलाएं

आशा है मैं समझ रहा हूँ :)


16
ओवरराइडिंग बहुरूपता प्रदान करता है, छायांकन पदानुक्रम के उस स्तर पर एक अलग कार्यान्वयन प्रदान करता है, लेकिन बहुरूपता नहीं।
डेविड रॉड्रिग्ज - dribeas

@dribeas, उस निष्कर्ष को निकालने के लिए आप किस बहुरूपता की परिभाषा का उपयोग करेंगे?
एंथनीवजन्स

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

2
मुझे लगता है, आप अपने नमूना कोड में एक त्रुटि है। कास्टिंग होना चाहिए ((ए) सीएलबी) .फू (), क्या यह नहीं होना चाहिए?
ट्रेंड

1
नहीं, क्योंकि बार आभासी है, इसलिए यह अब भी
स्ट्रोमेनेट

32

शैडिंग वास्तव में VB पार्लेंस है जिसे हम C # में छुपाने के लिए संदर्भित करेंगे।

अक्सर छिपाना (VB में छाया देना) और ओवरराइडिंग को स्टॉर्मनेट के उत्तर के रूप में दिखाया जाता है ।

एक वर्चुअल विधि को एक उप-वर्ग द्वारा ओवरराइड किया जाता है और सुपर-क्लास के प्रकार पर या सुपर-क्लास के अंदर कोड से उस विधि पर कॉल करने पर उप-वर्ग से प्रतिस्थापन कार्यान्वयन कहा जाएगा।

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

हालांकि अक्सर जो याद किया जाता है वह यह है कि आभासी विधि को छिपाना भी संभव है।

class A
{
    public virtual void DoStuff() { // original implementation }
}

class B : A
{
    public new void DoStuff() {  //new implementation }
}

B b = new B();
A a = b;

b.DoStuff(); //calls new implementation
a.DoStuff(); //calls original implementation.

उपरोक्त उदाहरण में नोट DoStuff ठोस हो जाता है और इसे ओवरराइड नहीं किया जा सकता है। हालाँकि यह virtualऔर newकीवर्ड दोनों का एक साथ उपयोग करना भी संभव है ।

class A
{
    public virtual void DoStuff() { // original implementation }
}

class B : A
{
    public new virtual void DoStuff() {  //new implementation }
}

class C : B
{
    public override void DoStuff() { //replacement implementation }
}

C c = new C();
B b = c;
A a = b;

c.DoStuff(); //calls replacement implementation
b.DoStuff(); //calls replacement implementation
a.DoStuff(); //calls original implementation.

ध्यान दें कि सभी विधियों के आभासी होने के बावजूद, C पर ओवरराइड newA को लागू करने के कारण A पर वर्चुअल विधि को प्रभावित नहीं करता है ।

संपादित करें: इसकी टिप्पणियों में इस उत्तर पर ध्यान दिया गया है कि उपरोक्त खतरनाक हो सकता है या कम से कम विशेष रूप से उपयोगी नहीं हो सकता है। मैं कहूंगा कि हाँ यह खतरनाक हो सकता है और अगर यह उपयोगी हो तो वहाँ से बाहर हो जाएगा।

विशेष रूप से आप हर तरह की परेशानी में पड़ सकते हैं यदि आप एक्सेसिबिलिटी मॉडिफ़ायर भी बदलते हैं। उदाहरण के लिए:-

public class Foo
{
    internal Foo() { }
    protected virtual string Thing() { return "foo"; }
}

public class Bar : Foo
{
 internal new string Thing() { return "bar"; }
}

के एक बाहरी उत्तराधिकारी के लिए Bar, Fooथिंग () का कार्यान्वयन प्रशंसनीय और अधिक होने योग्य है। .NET प्रकार के नियमों के अनुसार सभी कानूनी और व्याख्या योग्य, काफी अनपेक्षित नहीं।

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


2
जानकर अच्छा लगा। कम से कम इसका उपयोग खतरनाक हो सकता है :)
स्ट्रोमेनेट

2
जब सही तरीके से इस्तेमाल न किया जाए तो सभी उपकरण खतरनाक हो सकते हैं।
एंथनीवजोन

1
लेकिन, यह प्रयोज्य वास्तव में संदिग्ध लगता है! क्या इसका उपयोग करने वाला कोई 'गंभीर' ओपन-सोर्स ऐप है?
जोक्स

4
प्रयोज्य? क्या आपको उपयोगिता से मतलब है? जब तक आपको उनकी आवश्यकता होती है, तब तक के काम पर आने वाली समथिंग बेकार लग सकती है।
एंथनीवजन्स

ऐसा लगता है कि छायांकन केवल आभासी और नए नाटकों के दौरान चित्र में आता है। @ स्ट्रोमेनेट्स केवल ओवरराइड चीज की व्याख्या कर रहा है क्योंकि यह क्लास का सामान्य व्यवहार है जब तक कि यह आभासी न हो।
सुमित कपाड़िया

6

मुझे लगता है कि मुख्य अंतर यह है कि शैडोइंग के साथ, आप अनिवार्य रूप से नाम का पुन: उपयोग कर रहे हैं, और सिर्फ सुपरक्लास उपयोग की अनदेखी कर रहे हैं। ओवरराइडिंग के साथ, आप कार्यान्वयन को बदल रहे हैं, लेकिन पहुंच और हस्ताक्षर नहीं (जैसे पैरामीटर प्रकार और वापसी)। Http://www.geekinterview.com/question_details/19331 देखें ।


5

छायांकन एक VB.NET अवधारणा है। C # में, शैडोइंग को छुपा के रूप में जाना जाता है। यह व्युत्पन्न वर्ग विधि को छुपाता है। यह 'नए' कीवर्ड का उपयोग करके पूरा किया गया है।

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


तुम्हारा मतलब है। यह बेस क्लास पद्धति का उपयोग करने के बजाय व्युत्पन्न वर्ग विधि को छुपाता है। ?
शाइजुत

0

मूल रूप से अगर आपके पास नीचे जैसा कुछ है,

Class A
{
}

Class B:A
{
}

A a = new B();

ऑब्जेक्ट 'ए' पर कॉल करने वाली कोई भी विधि 'ए' के ​​प्रकार पर बनाई जाएगी (यहां टाइप 'ए' है) लेकिन यदि आप क्लास बी में पहले से मौजूद क्लास बी में उसी तरीके को लागू करते हैं, तो कंपाइलर करेगा आपको "नया" कीवर्ड का उपयोग करने के लिए एक चेतावनी दें। यदि आप "नया" का उपयोग करते हैं, तो चेतावनी गायब हो जाएगी। इसके अलावा "न्यू" का उपयोग करने या विरासत में मिली कक्षा में इसका उपयोग नहीं करने के बीच कोई अंतर नहीं है।

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

उम्मीद है की यह मदद करेगा...

डैनियल संदीप।


0

यदि कोई ऐसा मामला है जिसमें आप किसी वर्ग की सामग्री को बदल नहीं सकते हैं, तो आइए बताते हैं A, लेकिन आप इसके कुछ तरीकों का उपयोग करना चाहते हैं , साथ ही आपके पास एक विधि है जिसका नाम सामान्य है, आप newकीवर्ड द्वारा अपनी खुद की विधि का उपयोग कर सकते हैं ।

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

class A
{
    public void Test()
    {
        Console.WriteLine("base");
    }
}

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

    public static void Main(string[] args)
    {
        A a = new A();
        B aa = new B();
        a.Test();
        aa.Test();
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.