2012-03-01 9 views
66

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

public class Boom { 

    private void touchMe() { 
     System.out.println("super::I am not overridable!"); 
    } 

    private class Inner extends Boom { 

     private void touchMe() { 
      super.touchMe(); 
      System.out.println("sub::You suck! I overrided you!"); 
     } 
    } 

    public static void main(String... args) { 
     Boom boom = new Boom(); 
     Boom.Inner inner = boom.new Inner(); 
     inner.touchMe(); 
    } 
} 

यह संकलित और काम किया। "मैं बनाना चाहिए touchMe() अंतिम" मैंने सोचा था और यह किया:

public class Boom { 

    private final void touchMe() { 
     System.out.println("super::I am not overridable!"); 
    } 

    private class Inner extends Boom { 

     private void touchMe() { 
      super.touchMe(); 
      System.out.println("sub::You suck! I overrided you!"); 
     } 
    } 

    public static void main(String... args) { 
     Boom boom = new Boom(); 
     Boom.Inner inner = boom.new Inner(); 
     inner.touchMe(); 
    } 
} 

और यह भी काम करता है और मुझे

[email protected]:~$ java Boom 
super::I am not overridable! 
sub::You suck! I overrided you! 

क्यों कहता है?

+0

यह "छुपा" या "शैडोइन" या कुछ है। क्या बाहरी प्रकार का विस्तार बाहरी वर्ग का विस्तार करना थोड़ा बुरा है (यहां तक ​​कि वास्तव में भी, वास्तव में)।/'बूम आंतरिक = boom.new आंतरिक(); ' –

+23

का अच्छा उदाहरण है कि आपको @ ओवरराइड एनोटेशन का उपयोग क्यों करना चाहिए। सुनिश्चित करें कि आप वास्तव में विधि – Shawn

+0

पर ओवरराइड कर रहे हैं, क्या इसे 'सुपर ...' दो बार नहीं लिखना चाहिए? * अद्यतन * नहीं मी culpa। समझा। – DerMike

उत्तर

87

निजी तरीकों को ओवरराइड नहीं किया जा सकता है (निजी तरीके विरासत में नहीं हैं!) वास्तव में, यदि आप एक निजी विधि को अंतिम घोषित करते हैं या नहीं तो इससे कोई फर्क नहीं पड़ता है।

दो तरीकों आप घोषणा की है, Boom.touchMe और Boom.Inner.touchMe दो पूरी तरह से अलग तरीकों जो सिर्फ एक ही पहचानकर्ता साझा करने के लिए होता है। तथ्य यह है कि super.touchMetouchMe से भिन्न विधि को संदर्भित करता है, केवल Boom.Inner.touchMeछायाBoom.touchMe (और इसलिए नहीं कि यह इसे ओवरराइड करता है)।

इस तरीके का एक संख्या में प्रदर्शन किया जा सकता है:

  • आप अपने आप को पता चला है, यदि आप तरीकों को बदलने के सार्वजनिक होने के लिए, संकलक शिकायत क्योंकि आप अचानक एक अंतिम ओवरराइड करने के लिए कोशिश कर रहे हैं तरीका।

  • यदि आप विधियों को निजी रखते हैं और @Override एनोटेशन जोड़ते हैं, तो संकलक शिकायत करेगा।

  • alpian के रूप में बताते हैं, यदि आप एक Boom वस्तु (((Boom) inner).touchMe()) Boom.touchMe कहा जाता है (अगर यह वास्तव में ओवरराइड की गई थी, कलाकारों में कोई फर्क नहीं होता है) को Boom.Inner वस्तु डाली।

संबंधित प्रश्न:

+13

मैं इस पर गलत हो सकता हूं, लेकिन मेरा मानना ​​है कि एक महत्वपूर्ण गलतफहमी यह है कि 'super.touchMe()' का अर्थ है "इस विधि को ओवरराइड करने के तरीके को कॉल करें।" हालांकि यह अक्सर इस तरह से काम करता है, इसका वास्तव में मतलब है "इस कक्षा के वर्ग में 'touchMe()' विधि को कॉल करें। " यही कारण है कि आप 'super.touchMe() 'को कॉल कर सकते हैं - यह केवल एक विधि (उसी हस्ताक्षर के साथ) होता है। – corsiKa

+1

हाँ, धन्यवाद! अब मैं समझ गया। जब मैंने इसे सार्वजनिक किया तो मुझे संकलन-समय त्रुटि मिली। – chicout

+0

आपका स्वागत है। :-) – aioobe

2

आप विधि ओवरराइड कर सकते हैं, क्योंकि यह हर वर्ग के लिए private है।

6

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

@ ओवरराइड एनोटेशन जोड़ने का प्रयास करें - आपको एक कंपाइलर त्रुटि मिलेगी।

+1

"निजी विधियां ... किसी भी अन्य वर्ग के लिए अदृश्य हैं" - छोड़कर और जब तक आप प्रतिबिंब पर विचार नहीं करते। –

+0

सच है - लेकिन मुझे लगता है कि यह मूल प्रश्न के दायरे से बाहर है, और ओवर-राइडिंग मुद्दे को प्रभावित नहीं करेगा। – DNA

8

मैं इस तथ्य लगता है कि वहाँ वास्तव में दो अलग-अलग तरीकों यहाँ अच्छी तरह से बदलने के द्वारा प्रदर्शन किया है अपने मुख्य इस प्रकार है:

public static void main(String... args) { 
    Boom boom = new Boom(); 
    Boom.Inner inner = boom.new Inner(); 
    inner.touchMe(); 
    System.out.println("And now cast it..."); 
    ((Boom)(inner)).touchMe(); 
} 

यह अब प्रिंट:

super::I am not overridable! 
sub::You suck! I overrided you! 
And now cast it... 
super::I am not overridable! 

और कारण यह है कि कॉल superInner में काम करता है क्योंकि आप अपने सुपर-क्लास (Boom) में touchMe नामक एक विधि देख रहे हैं जो वास्तव में मौजूद है और Inner पर दिखाई देता है क्योंकि यह उसी सी में है लड़की।

1

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

public class Boom { 

    private final void touchMe() { 
     System.out.println("super [touchMe] ::I am not overridable!"); 
    } 

    public void overrideMe(){ 
     System.out.println("super [overrideMe]::I am overridable!"); 
    } 

    private class Inner extends Boom { 

     private void touchMe() { 
      super.touchMe(); 
      System.out.println("sub [touchMe]::You suck! I overrided you!"); 
     } 

     public void overrideMe(){ 
      System.out.println("sub [overrideMe] ::I overrided you!"); 
     } 
    } 

    public static void main(String... args) { 
     Boom boom = new Boom(); 
     Boom.Inner inner = boom.new Inner(); 

     inner.touchMe(); 

     Boom newBoom = inner; 
     newBoom.touchMe(); 
     newBoom.overrideMe(); 
    } 
} 



super [touchMe] ::I am not overridable! 
sub [touchMe]::You suck! I overrided you! 
super [touchMe] ::I am not overridable! 
sub [overrideMe] ::I overrided you! 
संबंधित मुद्दे