वर्चुअल तरीके क्या हैं?


81

आप एक विधि को "आभासी" क्यों घोषित करेंगे।

आभासी का उपयोग करने में क्या लाभ है?

जवाबों:


58

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

उदाहरण:

class A
{
    public virtual void Foo()
       //DoStuff For A
}

class B : A
{
    public override void Foo()
    //DoStuff For B

    //now call the base to do the stuff for A and B 
    //if required
    base.Foo()
}

45

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

public class Thingy
{
    public virtual void StepA()
    {
        Console.Out.WriteLine("Zing");
    }

    public void Action()
    {
        StepA();
        Console.Out.WriteLine("A Thingy in Action.");
    }
}

public class Widget : Thingy
{
    public override void StepA()
    {
        Console.Out.WriteLine("Wiggy");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Thingy thingy = new Thingy();
        Widget widget = new Widget();

        thingy.Action();
        widget.Action();

        Console.Out.WriteLine("Press any key to quit.");
        Console.ReadKey();
    }
 }

जब आप प्रोग्राम चलाते हैं तो आपका आउटपुट होगा:

Zing 
A Thingy in Action. 
Wiggy 
A Thingy in Action.

ध्यान दें कि भले ही विजेट को थिंगी स्तर पर परिभाषित क्रिया () विधि कहा जाता है, आंतरिक रूप से थिंगी को विजेट का चरण () विधि कहा जाता है।

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


23

एक आभासी विधि एक प्रकार की विधि है जहां वास्तविक विधि कॉल अंतर्निहित वस्तु के रनटाइम प्रकार पर निर्भर करती है।

एक गैर-आभासी विधि एक प्रकार की विधि है, जिसे वास्तविक विधि कहा जाता है, जो विधि आह्वान के बिंदु पर वस्तु के संदर्भ प्रकार पर निर्भर करती है।


यह एक उत्तर होना चाहिए - वर्चुअल को घोषणा के संशोधन के माध्यम से परिभाषित नहीं किया जा सकता है। यह छिपने की विधि से अलग कैसे है?
सेन्या

13

MSDN पर वर्चुअल तरीके

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

जब कोई वर्चुअल विधि लागू की जाती है, तो ओवरराइडिंग सदस्य के लिए रन-टाइम प्रकार की वस्तु की जाँच की जाती है। सबसे व्युत्पन्न वर्ग में ओवरराइडिंग सदस्य को कहा जाता है, जो मूल सदस्य हो सकता है, यदि किसी व्युत्पन्न वर्ग ने सदस्य को ओवरराइड नहीं किया है। (रन-टाइम प्रकार और सबसे अधिक व्युत्पन्न कार्यान्वयन के बारे में अधिक जानकारी के लिए, 10.5.3 वर्चुअल तरीके देखें।)

डिफ़ॉल्ट रूप से, विधियाँ गैर-आभासी होती हैं। आप एक गैर-आभासी विधि को ओवरराइड नहीं कर सकते।

आप निम्न संशोधक के साथ आभासी संशोधक का उपयोग नहीं कर सकते हैं:

स्थिर सार ओवरराइड

वर्चुअल प्रॉपर्टीज़ एब्सट्रैक्ट मेथड्स की तरह व्यवहार करती हैं, सिवाय डिक्लेरेशन और इनवोकेशन सिंटैक्स में अंतर के अलावा।

  • यह एक स्थिर संपत्ति पर आभासी संशोधक का उपयोग करने के लिए एक त्रुटि है।
  • एक आभासी विरासत में मिली संपत्ति को एक घोषित श्रेणी में शामिल किया जा सकता है जिसमें एक संपत्ति घोषणा शामिल है जो ओवरराइड संशोधक का उपयोग करती है।

6

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

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


5

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


4

एक छोटा सवाल, एक छोटा जवाब! अपने तरीके को "आभासी" के रूप में योग्य करें यदि आपको लगता है कि आप उस वर्ग के उत्तराधिकारी होंगे जो इसका है।

एक लंबा जवाब: "आभासी आपको एक अलग वर्ग में अपनी पद्धति का एक और अर्थ देने के लिए ओवरराइड करने में सक्षम बनाता है।


3

विरासत में मिली कक्षाओं में इसे ओवरराइड करने में सक्षम होने के लिए।

की जाँच करें MSDN प्रविष्टि कीवर्ड के लिए। जो इसे और गहराई से समझाता है।


1

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

ओपन बंद सिद्धांत के बारे में अधिक पढ़ें यहाँ , अंकल बॉब मूल ओसीपी श्वेतपत्र।

इसके अलावा pls ध्यान रखें कि जावा के विपरीत C # में डिफ़ॉल्ट रूप से विधियाँ आभासी नहीं हैं ।



1

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

    public class sample {
      public virtual void fun(){
        Console.WriteLine("base sample class \n");
      }
    }
    public class A : sample{
      public override void fun(){
        Console.WriteLine("Class A \n");
      }
    }
    public class B : sample{
      public override void fun(){
        Console.WriteLine("Class B \n");
      }
    }
    class run{
      public static void main(String[] args){
        sample obj = new sample();
        sample obj1 = new A();
        sample obj2 = new B();
        obj.fun();
        obj1.fun();
        obj2.fun();
      }
    }

"वास्तव में अस्तित्व में नहीं है" से आपका क्या तात्पर्य है? क्या आप एक संदर्भ प्रदान कर सकते हैं
मुबारक

यह सी # विरासत की तरह नहीं दिखता है। publicके बाद पहुँच संशोधक class Aऔर class Bकारणों संकलन समय त्रुटियों। व्युत्पन्न वर्ग से आधार वर्ग में सदस्यों की पहुँच को व्यक्तिगत आधार पर निर्दिष्ट किया जाता है, आधार वर्ग बनाते हैं (डिफ़ॉल्ट सदस्यों द्वारा private)।
मिन्ह ट्रैन

@ मिन्ह ट्रान - हाँ, आप सही हैं। वह c ++ वंशानुक्रम था। वैसे भी, मैंने पोस्ट को एडिट किया।
रेखा केश मोहन

1

संकलन समय के अनुसार होता है।
जब आप एक विधि को आभासी घोषित करते हैं, तो इसे व्युत्पन्न वर्ग में घोषित करने के लिए आपको एक overrideया newसंशोधक जोड़ने की आवश्यकता होती है ।
हम देख सकते हैं कि जब TrySpeak। बच्चे और पिता में पास होना, दोनों को पिता का बोलना, जबकि TryScream, प्रत्येक विधि कहेंगे।
इसे समझने के लिए, कुछ चीजें हैं जो हमें पता होनी चाहिए, एक उदाहरण में, Screamचाइल्ड क्लास या फादर क्लास से दो तरीके हैं । हम या तो Scream चाइल्ड क्लास या फादर क्लास से कॉल कर सकते थे । क्योंकि Virtaulसंशोधक विधि को चिह्नित करता है, इसलिए इसे व्युत्पन्न वर्ग द्वारा अधिलेखित किया जा सकता है, जिसका अर्थ है कि यहां तक ​​कि Screamपिता वर्ग से भी बुलाया जाता है, यह अतिरंजित है, यदि आप नए संशोधक का उपयोग करते हैं तो यह अपमानजनक होगा।

import system;
class Father
{
    Speak()
    {
        Console.Writeline("Father is speaking") 
    }
    virtual Scream()
    {
        Console.Writeline("Father is screaming")    
    }
}
class Child: father
{
    Speak()
    {
        Console.Writeline("Child is speaking")  
    }
    override Scream()
    {
        Console.Writeline("Child is screaming") 
    }
}
class APP
{
    public static void Main()
    {
        // We new two instances here
        Father father = new Father();
        Child child = new Child();        
        // Here we call their scream or speak through TryScream or TrySpeak
        TrySpeak(father);
        TrySpeak(child);
        //>>>"Father is speaking"
        //>>>"Father is speaking"
        TryScream(father);
        TryScream(child);
        //>>>"Father is screaming"
        //>>>"Child is screaming"
    }
    // when your method take an Parameter who type is Father
    // You can either pass in a Father instance or
    // A instance of a derived Class from Father
    // which could be Child
    public static void TrySpeak(Father person)
    {
        person.Scream();
    }
    public static void TryScream(Father person)
    {
        person.Speak();
    }
}

1

C # में, व्युत्पन्न वर्ग में आधार वर्ग विधि को ओवरराइड करने के लिए, आपको बेस क्लास पद्धति को आभासी और व्युत्पन्न वर्ग विधि को ओवरराइड के रूप में घोषित करना होगा:

using System;
namespace Polymorphism
{
 class A
 {
 public virtual void Test() { Console.WriteLine("A::Test()"); }
 }

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

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

 A a = new A();
 B b = new B();
 C c = new C();
 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "B::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

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

using System;
namespace Polymorphism
{
 class A
 {
 public void Test() { Console.WriteLine("A::Test()"); }
 }

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

 class C : B
 {
 public override void Test() { Console.WriteLine("C::Test()"); }
 }

 class Program
 {
 static void Main(string[] args)
 {

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

 a.Test(); // output --> "A::Test()"
 b.Test(); // output --> "B::Test()"
 c.Test(); // output --> "C::Test()"

 a = new B();
 a.Test(); // output --> "A::Test()"

 b = new C();
 b.Test(); // output --> "C::Test()"

 Console.ReadKey();
 }
 }
}

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

ओवरराइड कीवर्ड का उपयोग वर्चुअल क्लास / एब्सट्रैक्ट मेथड, प्रॉपर्टी, इंडेक्स या बेस क्लास की घटना को व्युत्पन्न वर्ग में विस्तार या संशोधित करने के लिए किया जाता है।

नए कीवर्ड का उपयोग बेस क्लास की विधि, प्रॉपर्टी, इंडेक्स या ईवेंट को छिपाने के लिए किया जाता है।

का आनंद लें :-)


-1

यह लिंक आपको बहुत ही आसान उदाहरण https://stackoverflow.com/a/2392656/3373865 के साथ एक बेहतर समझ प्रदान करेगा


1
यह केवल एक लिंक-केवल उत्तर नहीं है (कृपया लिंक के टूटने की स्थिति में, आपके उत्तर के भीतर लिंक की गई पोस्ट का पदार्थ शामिल करें), लेकिन C ++ के बारे में भी, न कि C # के बारे में। क्या यहां भी वही सिद्धांत लागू होते हैं?
मार्क्स पोलाकॉव्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.