2010-06-30 16 views
31

जब भी मैं इस विधि के कार्यान्वयन के अलावा, बेस क्लास की विधि को ओवरराइड करता हूं, तो मुझे लगता है कि 3 विकल्प हैं।बेस क्लास विधि को "ठीक से" ओवरराइड कैसे करें?

1) कॉल बेस। विधि(), और फिर मेरा कार्यान्वयन प्रदान करें।

2) मेरी कार्यान्वयन प्रदान करें और उसके बाद base.Method फोन()

3) बस मेरे कार्यान्वयन प्रदान करते हैं।

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

मैं एक उदाहरण लेगा।

public class ViewManager { 
    public virtual void Customize(){ 
     PrepareBaseView(); 
    } 
} 

public class PostViewManager { 
    public override void Customize(){ 
     base.Customize(); 
     PreparePostView(); 
    } 
} 


public class PreViewManager { 
    public override void Customize(){ 
     PreparePreView(); 
     base.Customize(); 
    } 
} 


public class CustomViewManager { 
    public override void Customize(){ 
     PrepareCustomView(); 
    } 
} 

यहाँ मेरा प्रश्न है कि कैसे कर सकते थे एक बच्चे कक्षा पता जनक वर्ग द्वारा की उम्मीद की जा रही है जो आदेश (या विकल्प) (आधार वर्ग कार्यान्वयन पर एक नज़र लेने के बिना)? क्या कोई तरीका है जिसमें अभिभावक वर्ग सभी व्युत्पन्न कक्षाओं में से तीन विकल्पों में से एक को लागू कर सकता है?

+1

'पोस्ट व्यूमेनगर', 'प्रीव्यूमेनगर', 'कस्टम व्यूमेनगर' 'ViewManager' से प्राप्त होता है? यदि ऐसा है, तो आपको कोड संपादित करना चाहिए। – LaTeX

उत्तर

36

बच्चे वर्ग को कैसे पता चलेगा (बेस क्लास कार्यान्वयन पर विचार किए बिना) कौन सा आदेश (या विकल्प) माता-पिता वर्ग द्वारा अपेक्षित किया जा रहा है?

जब आप उप-वर्गीकरण और विधि को ओवरराइड करते हैं तो इसे "जानना" का कोई तरीका नहीं है। उचित दस्तावेज वास्तव में यहां एकमात्र विकल्प है।

क्या कोई तरीका है जिसमें मूल वर्ग सभी व्युत्पन्न कक्षाओं में से तीन विकल्पों में से एक को लागू कर सकता है?

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

public class BaseClass { 
    public void Method() // Non-virtual 
    { 
      // Do required work 

      // Call virtual method now... 
      this.OnMethod(); 
    } 

    protected virtual void OnMethod() 
    { // Do nothing 
    } 
} 

उपवर्गों कर सकते हैं तो "ओवरराइड" OnMethod, और कार्यक्षमता के बाद "विधि" का कार्यालय होता है प्रदान करते हैं।

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

+1

आपने मुझे इसे हराया। यह ** भंगुर आधार वर्ग ** समस्या है। वर्कअराउंड के लिए +1 (जिसे आपने मुझे भी हराया :), ** टेम्पलेट विधि पैटर्न **। आप संरक्षित 'ऑनमेथ' सार भी बना सकते हैं ताकि व्युत्पन्न कक्षाएं जान सकें कि उनके पास अपना स्वयं का कार्यान्वयन प्रदान करने के लिए * है * और इसके अलावा उन्हें आधार कार्यान्वयन नहीं करना है (मानते हुए कि यह तुरंत शुरू करने के लिए समझ में नहीं आता है 'Base')। – shambulator

+0

+1 यह आपको अपने साथी डेवलपर्स के क्रोध से बचाएगा। – Marc

+0

@shambulator - ओवरराइड वैकल्पिक है, इसलिए शायद यह 'OnMethod' सार बनाने के लिए तुलनीय नहीं है। यह अभी भी एक अच्छा विकल्प है, हालांकि –

1

संक्षिप्त उत्तर नहीं है। आप बच्चे को मूल विधि कहने के क्रम में लागू नहीं कर सकते हैं, या यदि यह बिल्कुल कहता है।

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

1) बेस क्लास में एक गैर-वर्चुअल फ़ंक्शन बनाएं। आइए इसे MyFunction

2) बेस क्लास में संरक्षित वर्चुअल फ़ंक्शन बनाएं। आइए इसे कॉल करें _ MyFunction

3) कक्षाएं प्राप्त करने से _MyFunction विधि का विस्तार होता है।

4) MyFunction कॉल _ MyFunction है और उसे कॉल करने से पहले या बाद में चलाने के लिए आवश्यक कोड चलाएं।

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

+0

मुझे आश्चर्य है कि PostSharp जैसे कुछ आदेश को लागू कर सकते हैं। – FrustratedWithFormsDesigner

0

बेस क्लास की आवश्यकताओं को पुस्तकालय डिजाइनर द्वारा दस्तावेज किया जाना चाहिए। यह समस्या यही कारण है कि कुछ पुस्तकालयों में मुख्य रूप से मुहरबंद कक्षाएं होती हैं।

2

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

व्युत्पन्न वर्गों है कि संरक्षित आभासी विधि ओवरराइड आधार वर्ग कार्यान्वयन कॉल करने के लिए आवश्यक नहीं हैं:

जब अपने आप को कोड लिखने मैं हमेशा नियम है कि कहते हैं पालन करने के लिए थक गया है। बेस क्लास को सही ढंग से काम करना जारी रखना चाहिए, भले ही इसका कार्यान्वयन नहीं कहा जाता है।

यह http://msdn.microsoft.com/en-us/library/ms229011.aspx से लिया गया है, हालांकि यह इवेंट डिज़ाइन के लिए है, हालांकि मुझे लगता है कि मैंने इसे फ्रेमवर्क डिज़ाइन दिशानिर्देश पुस्तक (http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321246756) में पढ़ा है।

हालांकि, यह स्पष्ट रूप से सच नहीं है, उदाहरण के लिए एएसपी.नेट वेब फॉर्म पेज_लोड पर बेस कॉल की आवश्यकता है।

तो, लंबा और छोटा, यह भिन्न होता है और दुर्भाग्यवश जानने का कोई त्वरित तरीका नहीं है। अगर मुझे संदेह है तो मैं शुरुआत में कॉल छोड़ दूंगा।

+0

क्या एक अद्भुत जवाब है। मेरे सटीक विचार ऊपर मतदान किया। – Xtro

संबंधित मुद्दे