2012-10-12 28 views
5

मैंने सीखा है कि वर्चुअल विधियों का उपयोग किसी विधि/फ़ंक्शन के लिए डिफ़ॉल्ट व्यवहार प्रदान करता है। मेरी क्वेरी यह है कि, जब हम व्युत्पन्न वर्ग में "नया" का उपयोग करके उसी नाम (बेस क्लास में) के तरीके को कार्यान्वित कर सकते हैं और इसे अलग-अलग ऑब्जेक्ट्स द्वारा कॉल कर सकते हैं तो वर्चुअल विधि का उपयोग क्या होता है। उदाहरण के लिए;आभासी विधि का उपयोग कर केवल एक उदाहरण पीढ़ी का लाभ है?

class A 
{ 
     public void F() 
     { 
     //default behavior 
     } 

     public virtual void G() 
     { 
     //default behavior 
     } 
} 

class B:A 
{ 
    new public void F() 
    { 
     //new behavior from that of class A 
    } 
    public override void G() 
    { 
     //new behavior from that of class A 
    } 
} 

class Test 
{ 
    public static void Main(string[] args) 
    { 
     //For calling A's method use same compile time and run time object 
     A obj1 = new A(); 

     //For calling B's method use compile time object of A and run time of B 
     A obj2 = new B(); 

     obj1.F(); //O/P is A's method result 
     obj2.F(); //O/P is A's method result 
     obj1.G(); //O/P is A's method result 
     obj2.G(); //O/P is B's method result 
} 

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

A obj1 = new A(); //for calling A's methods 
B obj2 = new B(); //for calling B's methods 
A obj3 = new B(); //for having default behavior of class A using B's run time object. 

जो मैंने प्राप्त किया वह केवल आभासी के मामले में हमें एक ही संकलन और समय के प्रकार को चलाने की आवश्यकता नहीं है। यह एक ऑब्जेक्ट द्वारा प्राप्त किया जा सकता है जो टाइप ए के संकलन समय और बी बी

उत्तर

6

मेरा प्रश्न यह है कि कक्षा ए में वर्चुअल जी() की आवश्यकता होती है जब हम डिफ़ॉल्ट व्यवहार प्रदान कर सकते हैं समय संकलन और संकलन एक के समय वस्तु का उपयोग करके समय वस्तु और व्युत्पन्न व्यवहार चलाने के लिए और बी

के समय चलाने

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

उदाहरण के लिए, मैं Stream.Read और Stream.Write का उपयोग कर एक स्ट्रीम की सामग्री को प्रतिलिपि बनाने के लिए एक विधि लिख सकता हूं क्योंकि वे आभासी या अमूर्त विधियां हैं। इससे कोई फ़र्क नहीं पड़ता कि कौन से कार्यान्वयन पारित किए गए हैं।

आपको विधि मोडिफ़ायर के रूप में बहुत ही कम new का उपयोग करना चाहिए - यदि आप वास्तव में गैर-वर्चुअल विधि के लिए अलग-अलग व्यवहार प्रदान करना चाहते हैं, तो यह बहुत स्पष्ट है कि आप एक बिल्कुल अलग बनाते हैं विधि का नाम, ताकि कोड पढ़ने वाला कोई भी व्यक्ति समझ सके कि बेस क्लास में घोषित एक से एक बहुत ही अलग विधि है।

+0

शायद मेरा दिमाग उत्तर से नहीं सुलझाया गया है ... मैं इसे स्पष्ट रूप से प्राप्त नहीं कर पा रहा हूं। क्या आप इसे अधिक यथार्थवादी स्पर्श दे सकते हैं और तत्काल उत्तर के लिए हाँ धन्यवाद। – user1740176

+0

मुझे डर है कि मुझे नहीं पता कि "अधिक यथार्थवादी स्पर्श" से आपका क्या मतलब है। –

+0

अच्छा खेद है कि स्पष्ट नहीं होना चाहिए। मैं यह पूछने की कोशिश कर रहा था: क्या वर्चुअल विधि का उपयोग केवल स्मृति को बचाता है? तो अधिक वस्तुओं को बनाने के लिए या इसके अलग-अलग कारण भी हैं? यथार्थवादी स्पर्श से मेरा मतलब था कि कोई वास्तविक जीवन उदाहरण। – user1740176

0

जॉन एक कारण बताता है कि यदि आप कार्यान्वयन को छिपाते हैं तो आधार वर्ग में विधि के किसी भी संदर्भ का आधार आधार कार्यान्वयन के लिए है, जबकि यदि आप बेस क्लास में भी किसी भी आमंत्रण को ओवरराइड करते हैं तो ओवरराइडिंग विधि का उपयोग करता है

protected virtual void Foo(){ 
} 

private void Bar() { 
    //do generic stuff 
    Foo(); 
} 

यदि कोई वर्ग foo को ओवरराइड करता है तो वह कॉलिंग बार के प्रभाव को बदल देगा। यह कुछ डिजाइन पैटर्न की नींव है जैसे कि सार टेम्पलेट

+0

आपके उत्तर Rune के लिए धन्यवाद। माफ़ी, आपका उदाहरण नहीं मिल सका। – user1740176