2011-12-09 13 views
8

निम्न उदाहरण में कॉलिंग:एक निर्माता से एक ओवरराइड विधि

class Base {  
    int x=10; 

    Base() {  
     show(); 
    } 

    void show() { 
     System.out.print ("Base Show " +x + " "); 
    } 
} 

class Child extends Base { 
    int x=20; 

    Child() { 
     show(); 
    } 

    void show() {  
     System.out.print("Child Show " + x +" ") ; 
    } 

    public static void main(String s[ ]) { 
     Base obj = new Child(); 
    } 
} 
  • क्यों के रूप में नीचे
Child Show 0 Child Show 20 
  • मैंने सोचा था कि कंस्ट्रक्टर्स कर सकते हैं दिखाया उत्पादन होता है एक बार इसके सुपर कन्स्ट्रक्टर के बाद केवल इंस्टेंस सदस्यों तक पहुंचें एस पूरा हो गया है

मुझे लगता है कि यहां क्या हो रहा है यह है कि सुपर कन्स्ट्रक्टर बच्चे के शो() विधि को बुला रहा है क्योंकि इस विधि को बाल में ओवरराइड किया गया था। क्योंकि इसे ओवरराइड किया गया है लेकिन सुपर कन्स्ट्रक्टर पूरा होने से पहले x 0 का मान क्यों है और यह इस विधि तक पहुंचने में सक्षम क्यों है?

+0

आभासी हैंडलिंग तंत्र एक वस्तु के निर्माण के दौरान सक्षम है? मुझे शक है कि यह नहीं है। – Mahesh

+0

सी ++ में यह एक दुर्घटना का कारण बन सकता है। –

+3

प्रभावी जावा एक महान जावा संसाधन है और यह इसमें बहुत विस्तार से जाता है। आइटम 17 से: "*** रचनाकारों को ओवरराइड करने योग्य तरीकों का आह्वान नहीं करना चाहिए **, सीधे या परोक्ष रूप से (...) यदि ओवरराइडिंग विधि सबक्लास कन्स्ट्रक्टर द्वारा किए गए किसी भी प्रारंभिकरण पर निर्भर करती है, तो विधि अपेक्षित व्यवहार नहीं करेगी ... * "यदि आपके पास हाथ की किताब है तो मैं इस आइटम को पढ़ने की अत्यधिक अनुशंसा करता हूं। –

उत्तर

11

मुझे लगता है कि यहां क्या हो रहा है यह है कि सुपर कन्स्ट्रक्टर बच्चे के शो() विधि को बुला रहा है क्योंकि इस विधि को बाल में ओवरराइड किया गया था।

यह सही

है लेकिन क्यों (बाल का एक्स)

अभी तक क्योंकि यह प्रारंभ नहीं किया गया है एक्स 0

का मूल्य है और क्यों यह सक्षम है सुपर कन्स्ट्रक्टर पूरा होने से पहले इस विधि तक पहुंचने के लिए?

यही कारण है कि एक निर्माता में आपको कभी भी एक विधि नहीं बुलानी चाहिए, जिसे ओवरराइड किया जा सकता है (गैर-अंतिम सार्वजनिक और संरक्षित)।

संपादित करें:

यहाँ अजीब बात सब कुछ डिफ़ॉल्ट/पैकेज-निजी दृश्यता किया है। इसमें कुछ अजीब प्रभाव हो सकते हैं। देखें: http://www.cooljeff.co.uk/2009/05/03/the-subtleties-of-overriding-package-private-methods/

यदि संभव हो तो मैं डिफ़ॉल्ट दृश्यता के साथ ओवरराइडिंग विधियों से बचने की सलाह देता हूं (आप उन्हें अंतिम घोषित करके रोक सकते हैं)।

+1

+1 अनुक्रम मुख्य है -> चाइल्ड() -> बेस() -> Child.show() [x अभी तक शुरू नहीं हुआ] -> बेस.शो() [बेस.एक्स = 20] – stacker

+0

से पहले नहीं, नहीं, अनुक्रम मुख्य है -> बेस() -> Child.show() [x अभी तक शुरू नहीं हुआ] -> चाइल्ड() [Child.x = 20] -> Child.show() – Puce

+0

चाइल्ड क्लास पर चर एक्स है ऑब्जेक्ट क्लास पूरा होने पर 0 का डिफ़ॉल्ट मान दिया गया है? क्योंकि जहां तक ​​मुझे याद है यहां अनुक्रम है: नया बच्चा() -> आधार() -> ऑब्जेक्ट -> शो के बच्चे के कार्यान्वयन() ... – anathema

6

आप कंस्ट्रक्टर्स से ओवरराइड तरीकों कॉल कर सकते हैं, लेकिन यह बुरा है और आप नहीं करना चाहिए। आपने कारण खराब किया है कि यह क्यों बुरा है: व्युत्पन्न वर्ग को आरंभ करने का मौका नहीं मिलता है, इसलिए अनियमित फ़ील्ड का उपयोग किया जाएगा - आपके उदाहरण में, int x के लिए डिफ़ॉल्ट 0 है, यही कारण है कि यह 0 प्रिंट कर रहा है।

1

Childshow विधि का ओवरराइड लागू किया गया है क्योंकि जावा स्पेक के लिए यही कहा जाता है। यहां एक great discussion of why you should not do it है। एक्स का मान शून्य है क्योंकि Child अभी तक प्रारंभ नहीं हुआ है।

2

कन्स्ट्रक्टर चेनिंग यह समझाने के लिए समझ में आता है कि वास्तव में क्या है। एक सबक्लास कन्स्ट्रक्टर विधि का पहला कार्य अपने सुपरक्लास 'कन्स्ट्रक्टर विधि को कॉल करना है।यह सुनिश्चित करता है कि उपclass वस्तु का निर्माण विरासत श्रृंखला में इसके ऊपर की कक्षाओं के प्रारंभिकरण के साथ शुरू होता है।

http://java.about.com/b/2009/02/07/java-term-of-the-week-constructor-chaining.htm

http://javahours.blogspot.com/2008/12/constructor-chain.html

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