2011-04-04 7 views
20

मैं एक अमूर्त वर्ग में कुछ कोड देख रहा था:शरीर के बिना आभासी तरीकों

public virtual void CountX(){} 

public virtual void DoCalculation() { ...code} 

क्यों मैं एक अमूर्त वर्ग में एक खाली आभासी प्रणाली की घोषणा चाहिए, अगर यह व्युत्पन्न प्रकार में ओवरराइड कर अनिवार्य नहीं है?

+0

विषाणु। हाँ :) – Heliac

उत्तर

6

जैसा कि @ एडम ने आपको बताया था, ऐसे कई मामले हैं जिनमें यह समझ में आता है। जब आप एक अमूर्त वर्ग बनाते हैं, तो ऐसा इसलिए होता है क्योंकि आप उस वर्ग से प्राप्त सभी वर्गों के लिए एक सामान्य इंटरफ़ेस बनाना चाहते हैं; हालांकि, विरासत के उस स्तर पर आपके पास उस विधि के लिए कार्य कोड बनाने में सक्षम होने के लिए पर्याप्त जानकारी नहीं होगी।

उदाहरण के लिए, यदि आप वर्ग चित्रा, getArea() विधि के साथ बनाते हैं, आप नहीं कोड है कि सही ढंग से सभी आंकड़े के लिए क्षेत्र की गणना करने के लिए जा रहा है लिखने के लिए सक्षम हो जाएगा। आपको आयताकार, या सर्किल (दोनों चित्र से प्राप्त करने वाले दोनों) के लिए कोड लिखने में सक्षम होने के लिए कोड लिखने के लिए प्रतीक्षा करनी होगी।

+5

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

+4

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

36

क्योंकि यदि डिफ़ॉल्ट व्यवहार कुछ भी नहीं करना है, लेकिन कक्षाएं प्राप्त हो सकती हैं कुछ करना चाहते हैं। यह एक पूरी तरह से वैध संरचना है।

यह आपके बेस कोड को कॉल करने की अनुमति देता है। बेस क्लास पर "पहले XXX" और "आफ्टर एक्सएक्स" कोड होने पर आपको समान डिज़ाइन दिखाई देते हैं, यह कोड खाली है, लेकिन विधि को संकलित करने के लिए वहां होना आवश्यक है। व्युत्पन्न कक्षाओं में, यह कोड वैकल्पिक है, लेकिन इसे ओवरराइड करने के लिए वर्चुअल होने की आवश्यकता है।

तथ्य यह है कि यह एक अमूर्त वर्ग में है, इसे अपने व्यवहार को भ्रमित नहीं करना चाहिए।

एक उदाहरण:

abstract class Base 
    { 
     public void ProcessMessages(IMessage[] messages) 
     { 
      PreProcess(messages); 

      // Process. 

      PostProcess(messages); 
     } 

     public virtual void PreProcess(IMessage[] messages) 
     { 
      // Base class does nothing. 
     } 

     public virtual void PostProcess(IMessage[] messages) 
     { 
      // Base class does nothing. 
     } 
    } 

    class Derived : Base 
    { 
     public override void PostProcess(IMessage[] messages) 
     { 
      // Do something, log or whatever. 
     } 

     // Don't want to bother with pre-process. 
    } 

तो इन तरीकों (पूर्व, पोस्ट) सार थे, तो सभी व्युत्पन्न वर्ग होगा जरूरत उन्हें (संभावना के रूप में खाली विधि) लागू करने के लिए - कोड कूड़े का उपयोग कर हटाया जा सकता है आधार पर खाली आभासी तरीकों।

+0

+1 - प्री- और पोस्ट-प्रोसेसिंग एक महान उदाहरण है। – Town

+0

+1: आपने मूल कार्यान्वयन का वर्णन _default_ व्यवहार के रूप में किया है। वर्चुअल गैर-अमूर्त तरीकों का यही उद्देश्य है। यहां तक ​​कि जब डिफ़ॉल्ट "कुछ भी नहीं" होता है, यह अभी भी एक डिफ़ॉल्ट है;) –

+0

हम्म, इसलिए यदि मेरे पास "कुछ भी नहीं" आधार विधि है, * * मुझे * आधार से कॉल करना चाहिए। इस से कुछ नहीं। विधि नहीं है, या यह ठीक है कोड का टुकड़ा छोड़ने के लिए? – Heliac

3

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

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

4

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

0

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

+0

यदि आप वोट नीचे जा रहे हैं। कृपया कम से कम एक कारण प्रदान करें। – ComeIn

+0

मैं कॉमेलन से सहमत हूं। यहां डीकास्ट्रो की पोस्ट (http://stackoverflow.com/questions/22256157/empty-virtual-method-on-base-class-vs-abstract-methods) इस पर अधिक प्रकाश डालती है। – Kwex