हम ओवरराइड और वर्चुअल का उपयोग क्यों करते हैं यदि यह समान प्रभाव देता है जब हम ओवरराइड और वर्चुअल का उपयोग नहीं करते हैं?

उदाहरण 1:

class BaseClass
{
    public virtual string call()
    {
        return "A";
    }
}

class DerivedClass : BaseClass
{
    public override string call()
    {
        return "B";
    }
}

आउटपुट : B

उदाहरण 2:

class BaseClass
{
    public string call()
    {
        return "A";
    }
}

class DerivedClass : BaseClass
{
    public string call()
    {
        return "B";
    }
}

और आउटपुट अभी भी वही है:

आउटपुट : B

परीक्षण चलाने के लिए:

class Program
{
    static void Main(string[] args)
    {
        DerivedClass dc = new DerivedClass();
        Console.WriteLine(dc.call());
        Console.ReadKey();
    }
}

क्या कंपाइलर वर्चुअल जोड़ता है और संकलन समय पर स्वचालित रूप से ओवरराइड करता है?

मुझे खुशी होगी अगर कोई मुझे वर्चुअल और ओवरराइड का उपयोग करने का कारण बताएगा।

c#
16
Racooon 24 अक्टूबर 2011, 16:26

4 जवाब

सबसे बढ़िया उत्तर

(ध्यान दें, मैं चुपचाप संकलन त्रुटियों की अनदेखी कर रहा हूँ)

अब करें:

BaseClass obj = new DerivedClass();
Console.WriteLine(obj.call());

virtual के बिना, यह A प्रिंट करेगा, जब वास्तव में एक DerivedClass B लिख रहा होगा। ऐसा इसलिए है क्योंकि इसे केवल BaseClass कार्यान्वयन कहा गया है (चूंकि obj को BaseClass के रूप में टाइप किया गया है, और कोई बहुरूपता परिभाषित नहीं है)।

21
Marc Gravell 24 अक्टूबर 2011, 17:00

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

http://en.wikipedia.org/wiki/Inheritance_(object-oriented_programming )

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

वर्चुअल और ओवरराइड आपको किसी विधि की सामग्री को बदलने की अनुमति देते हैं, और जब मैं कहता हूं कि प्रतिस्थापित करें, तो मैं कहता हूं कि प्रतिस्थापित करें।

मैं आपको एक अच्छा उदाहरण प्रस्तावित करूंगा।

public class MyClassEnglish
{
    public virtual string SomethingToSay()
    {
        return "Hello!";
    }

    public void WriteToConsole()
    {
        Console.WriteLine(this.SomethingToSay());
    }
}

public class MyClassItalian :
    MyClassEnglish
{
    public override string SomethingToSay()
    {
        return "Ciao!";
    }
}

int main()
{
    MyClassItalian it = new MyClassItalian();

    it.WriteToConsole();
}

यदि आप वर्चुअल को छोड़ देते हैं और ओवरराइड करते हैं, तो MyClassItalian "हैलो!" का प्रिंट आउट लेगा। और "सियाओ!" नहीं।

आपके उदाहरण में आप एक शैडोइंग तकनीक दिखाते हैं, लेकिन संकलक को आपको एक चेतावनी देनी चाहिए। यदि आप किसी आधार वर्ग में कोई विधि छिपाना चाहते हैं तो आपको "नया" कीवर्ड जोड़ना चाहिए। एक विधि छुपाना ओवरराइड नहीं कर रहा है! छुपा ही रहा है।

एक संभावित उपयोग जो मेरे दिमाग में आता है वह यह है कि इसका उपयोग तब किया जा सकता है जब आपको उदाहरण के लिए किसी प्रकार के अनुकूलन की आवश्यकता हो।

public abstract class MySpecialListBase
{
    public int Count()
    {
        return this.GetCount();
    }

    protected abstract int GetCount();
}

public sealed class MySpecialArrayList : MySpecialListBase
{
    int count;

    public new int Count()
    {
        return this.count;
    }

    protected override int GetCount()
    {
        return this.count;
    }
}

अब... आप अपने सभी कोड में MySpecialListBase का उपयोग कर सकते हैं, और जब आप काउंट () को कॉल करते हैं तो यह वर्चुअल विधि GetCount () को कॉल करेगा। लेकिन यदि आप केवल MySpecialArrayList का उपयोग करते हैं तो यह अनुकूलित गणना() को कॉल करेगा जो वर्चुअल नहीं है और जो केवल एक फ़ील्ड लौटाता है, प्रदर्शन बढ़ाता है।

// This works with all kind of lists, but since it is a more general purpose method it will call the virtual method.    
public void MyMethod(MySpecialListBase list)
{
    Console.WriteLine(list.Count());
}

// This works only with MySpecialArrayList, and will use the optimized method.
public void MyMethod(MySpecialArrayList list)
{
    Console.WriteLine(list.Count());
}
5
Salvatore Previti 24 अक्टूबर 2011, 17:22

सबसे अच्छा उदाहरण मैं सोच सकता हूं कि यह कहां उपयोगी है जब आप अपनी खुद की वस्तु (वर्ग) बनाते हैं और आपको उस वस्तु की एक सूची को एक combobox में जोड़ना होगा।

जब आप अपने ऑब्जेक्ट को combobox में जोड़ते हैं तो आप यह नियंत्रित करने में सक्षम होना चाहते हैं कि प्रत्येक आइटम के लिए कौन सा टेक्स्ट प्रदर्शित होता है। Object.toString एक आभासी विधि है। http://msdn.microsoft.com/en-us/library /system.object.tostring.aspx और इस वजह से आप उस विधि को ओवरराइड कर सकते हैं और .toString को ओवरराइड करके अपने ऑब्जेक्ट के बारे में सही जानकारी प्रदर्शित करने के लिए सेट कर सकते हैं।

public MyClass()
{
     private int ID;
     public override string ToString()
     {
         return "My Item:" + ID;
     }
}
0
Gage 24 अक्टूबर 2011, 18:01

विधि अधिभावी:

जहां आप पैरेंट क्लास में वर्चुअल मेथड को परिभाषित या लागू करते हैं और फिर उसे डिसेंटेंट क्लास में बदल देते हैं।

जब आप किसी विधि को वर्चुअल घोषित करने का निर्णय लेते हैं, तो आप व्युत्पन्न कक्षाओं को अपने स्वयं के कार्यान्वयन के साथ विधि को बढ़ाने और ओवरराइड करने की अनुमति दे रहे हैं। आप विस्तारित विधि को मूल विधि के कोड को भी कॉल कर सकते हैं।

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

सी # ओवरराइडिंग सी # में, आप वर्चुअल विधि को वर्चुअल कीवर्ड के साथ पैरेंट क्लास में निर्दिष्ट करते हैं और ओवरराइड कीवर्ड का उपयोग करके इसे वंशज वर्ग में विस्तारित (या प्रतिस्थापित) करते हैं।

मूल विधि में कोड को निष्पादित करने के लिए मूल कीवर्ड का उपयोग करें, अर्थात base.SomeMethod ()।

सिंटैक्स उदाहरण:

class Robot
{
  public virtual void Speak()
  {
  }
}

class Cyborg:Robot
{
   public override void Speak()
   {
   }
}

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

using System;

class Dog
{
   public virtual void Bark()
   {
       Console.WriteLine("RUFF!");
   }
}

class GermanShepard:Dog
{
    public override void Bark()
    {
       Console.WriteLine("Rrrrooouuff!!");
    }
}

class Chiuaua:Dog
{
    public override void Bark()
    {
         Console.WriteLine("ruff");
    }
}
class InclusionExample
{
     public static void Main()
     {
        Dog MyDog=new Dog();    
        MyDog=new GermanShepard();
        MyDog.Bark(); // prints Rrrrooouuff!!

        MyDog=new Chiuaua();
        MyDog.Bark(); // prints ruff;
    }
}

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

नए और ओवरराइड संशोधक के अलग-अलग अर्थ हैं। नया संशोधक समान नाम, हस्ताक्षर और दृश्यता के साथ एक नया सदस्य बनाता है और मूल सदस्य को छुपाता है। ओवरराइड संशोधक एक विरासत में मिले सदस्य के लिए कार्यान्वयन का विस्तार करता है और आपको विरासत-आधारित बहुरूपता को लागू करने की अनुमति देता है।

नए सदस्यों का परिचय देने से बचें: कभी-कभी एक ही नाम, हस्ताक्षर और मूल विधि की दृश्यता के साथ एक नई विधि शुरू करने के स्पष्ट कारण होते हैं। उन स्पष्ट मामलों में, एक नए सदस्य का परिचय एक शक्तिशाली विशेषता है। हालाँकि, यदि आपके पास कोई स्पष्ट कारण नहीं है, तो नई विधि को कुछ अनोखा और उपयुक्त नाम देकर विधि के नए संस्करण को पेश करने से बचें।

class Robot : System.Object
{
  public void Speak()
  {
    MessageBox.Show("Robot says hi");
  }
}

class Cyborg : Robot
{
  new public void Speak()
  {
    MessageBox.Show("hi");
  }
}

बेस क्लास संस्करण को कॉल करना एक सामान्य कार्य OO में पहले मूल विधि कोड को निष्पादित करके और फिर कोड जोड़कर एक विधि का विस्तार करना है। मूल वर्ग को आधार के रूप में संदर्भित करने के लिए मूल कीवर्ड का उपयोग करें। कुछ विधि ()।

class Robot : System.Object
{
    public virtual void Speak()
    {
       MessageBox.Show("Robot says hi");
    }
}
class Cyborg : Robot
{
  public override void Speak()
  {
      base.Speak(); 
      MessageBox.Show("hi");
  }
}
0
Enigma State 24 अक्टूबर 2011, 23:06