2012-10-09 7 views
6

मैं जावा में विरासत का लटका पाने की कोशिश कर रहा हूं और सीखा है कि उप वर्गों में विधियों (और छुपा क्षेत्रों) को ओवरराइड करते समय, उन्हें अभी भी एक्सेस किया जा सकता है 'सुपर' कीवर्ड का उपयोग करके सुपर क्लास।गैर-ओवरराइड सुपरक्लास विधियों तक पहुंचने पर 'सुपर' कीवर्ड का उपयोग

मैं क्या जानना चाहता हूं, क्या 'अति' कीवर्ड को गैर-ओवरराइड विधियों के लिए उपयोग किया जाना चाहिए?

क्या कोई अंतर है (गैर-ओवरराइड विधियों/गैर-छिपे हुए फ़ील्ड के लिए)?

मैंने नीचे एक उदाहरण दिया है।

public class Vehicle { 
    private int tyreCost; 

    public Vehicle(int tyreCost) { 
     this.tyreCost = tyreCost; 
    } 

    public int getTyreCost() { 
     return tyreCost; 
    }   
} 

और

public class Car extends Vehicle { 
    private int wheelCount; 

    public Vehicle(int tyreCost, int wheelCount) { 
     super(tyreCost); 
     this.wheelCount = wheelCount; 
    } 

    public int getTotalTyreReplacementCost() { 
     return getTyreCost() * wheelCount; 
    } 
} 

विशेष रूप से, यह देखते हुए कि getTyreCost() अधिरोहित नहीं किया गया है, getTotalTyreReplacementCost() उपयोग getTyreCost(), या super.getTyreCost() चाहिए?

मुझे आश्चर्य है कि सुपर उदाहरणों के लिए फ़ील्ड या विधियों का उपयोग किया जा सकता है (कोड में दिखाया गया है कि आप सुपरक्लास तक पहुंच रहे हैं), या केवल ओवरराइड/छुपे हुए लोगों में (इसलिए वे अलग दिखना)।

उत्तर

10

super कीवर्ड का उपयोग अन्य विधियों को संदर्भित करने के लिए न करें जो ओवरराइड नहीं हैं। यह आपके वर्गों को बढ़ाने की कोशिश कर रहे अन्य डेवलपर्स के लिए भ्रमित करता है।

चलिए कुछ कोड देखें जो इस तरह से super कीवर्ड का उपयोग करें। Dog और CleverDog: यहाँ हम 2 वर्ग

/* file Dog.java */ 
public static class Dog extends Animal { 

    private String name; 

    public Dog(String name) { 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

} 

/* file CleverDog.java */ 
public class CleverDog extends Dog { 

    public CleverDog(String name) { 
     super(name); 
    } 

    public void rollover() { 
     System.out.println(super.getName()+" rolls over!"); 
    } 

    public void speak() { 
     System.out.println(super.getName() + " speaks!"); 
    } 

} 
अब

, कल्पना करें कि आप इस परियोजना पर एक नया डेवलपर हैं, और आप एक चतुर कुत्ता जो टीवी पर है के लिए कुछ विशिष्ट व्यवहार की जरूरत है: कि कुत्ते सब करना है इसकी चाल है, लेकिन अपने कल्पित टीवी नाम से जाना चाहिए। इसे पूरा करने के आप getName(...) विधि ओवरराइड ...

/* file DogOnTv.java */ 
public class DogOnTv extends CleverDog { 

    String fictionalName; 

    public DogOnTv(String realName, String fictionalName) { 
     super(realName); 
     fictionalName = fictionalName; 
    } 

    public String getName() { 
     return fictionalName; 
    } 

} 

... और एक जाल मूल निर्माता और super कीवर्ड के अपने असामान्य उपयोग द्वारा निर्धारित में गिर जाते हैं!

ऊपर कोड काम करने के लिए नहीं जा रहा है - क्योंकि मूल CleverDog कार्यान्वयन में, getName()super कीवर्ड का उपयोग शुरू हो जाती है। इसका मतलब है कि यह हमेशा Dog.getName() का आह्वान करता है - किसी भी ओवरराइडिंग के अप्रासंगिक। नतीजतन, जब आप अपने नए DogOnTv प्रकार का उपयोग करें ...

System.out.println("Showcasing the Clever Dog!"); 
    CleverDog showDog = new CleverDog("TugBoat"); 
    showDog.rollover(); 
    showDog.speak(); 

    System.out.println("And now the Dog on TV!"); 
    DogOnTv dogOnTv = new DogOnTv("Pal", "Lassie"); 
    dogOnTv.rollover(); 

... आप गलत आउटपुट प्राप्त:

Showcasing the Clever Dog! 
Tugboat rolls over! 
Tugboat speaks! 

And now the Dog on TV! 
Pal rolls over! 
Pal speaks! 

यह सामान्य अपेक्षित व्यवहार है जब आप एक विधि पर हावी नहीं है, तो आप super कीवर्ड का उपयोग करके इस तरह के भ्रम पैदा करने से बचना चाहिए जहां यह संबंधित नहीं है।

, अगर, हालांकि, यह वास्तव में व्यवहार आप चाहते है बजाय final कीवर्ड का उपयोग - स्पष्ट रूप से संकेत मिलता है कि विधि ओवरराइड नहीं किया जा सकता है:

/* file CleverDog.java */ 
public class CleverDog extends Dog { 

    public CleverDog(String name) { 
     super(name); 
    } 

    public final String getName() { // final so it can't be overridden 
     return super.getName(); 
    } 

    public void rollover() { 
     System.out.println(this.getName()+" rolls over!"); // no `super` keyword 
    } 

    public void speak() { 
     System.out.println(this.getName() + " speaks!"); // no `super` keyword 
    } 

} 
-1

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

1

आप super उपयोग करते हैं, आप स्पष्ट रूप से सुपर वर्ग विधि का उपयोग करने (अधिरोहित विधि यदि हो तो), कह रहे हैं (उप वर्ग पर ध्यान दिए बिना विधि अधिरोहित किया है या नहीं), उपवर्ग में विधि के लिए अन्यथा पहले JVM जांच करता है कि नहीं उपलब्ध का उपयोग करता है सुपर क्लास विधि।

0

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

3

getTyreCost तक पहुंचने के लिए आप super कीवर्ड का उपयोग न करके सही तरीके से कर रहे हैं।

लेकिन आपको अपने सदस्यों को निजी सेट करना चाहिए और केवल गेटर विधि का उपयोग करना चाहिए।

super का उपयोग कर कीवर्ड को रचनाकारों और ओवरराइड विधियों के लिए आरक्षित किया जाना चाहिए जिन्हें स्पष्ट रूप से मूल विधि को कॉल करने की आवश्यकता है।

+0

अच्छा स्थान (यह सिर्फ एक उदाहरण मैंने लिखा था प्रश्न के हिस्से के रूप में)। सदस्यों को अब अद्यतन और निजी पर सेट। – Jonny

2

यह इस बात पर निर्भर करेगा कि आप कोड का उपयोग करने की योजना कैसे बनाते हैं। यदि आप super.getTyreCost() निर्दिष्ट करते हैं और उसके बाद उस विधि को ओवरराइड करते हैं। आप अभी भी सुपरक्लास पर विधि को कॉल करेंगे, न कि ओवरराइड संस्करण।

मेरी राय में, कॉलिंग सुपर को बाद में अधिक भ्रम पैदा करने की संभावना है, इसलिए शायद आपको केवल तभी निर्दिष्ट किया जा सकता है जब आपको ऐसा करने की स्पष्ट आवश्यकता हो। हालांकि, यदि आपने यहां प्रस्तुत किया है - व्यवहार में कोई अंतर नहीं होगा।

2

यह आपकी आवश्यकताओं और आपकी इच्छाओं पर निर्भर करता है। super का उपयोग संकलन/एप्लिकेशन को आपके वर्तमान वर्ग में किसी भी संभावित विधियों को अनदेखा करने के लिए मजबूर करता है।यदि आप संवाद करना चाहते हैं कि आप केवल माता-पिता की विधि का उपयोग करना चाहते हैं, तो super का उपयोग करना उचित है। यह आपकी कक्षा में भविष्य में संशोधनों को गलती से पैरेंट विधि को ओवरराइड करने से रोक देगा जिससे आपके अपेक्षित तर्क को बर्बाद कर दिया जा सकेगा।

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

0

तकनीकी रूप से, इस मामले में जो भी शामिल है वह विरासत संस्करण है, जिसके लिए कार्यान्वयन वास्तव में मूल वर्ग द्वारा प्रदान किया जाता है।

ऐसे परिदृश्य हो सकते हैं जहां आपको super कीवर्ड का उपयोग करना होगा। जैसे यदि Car ने स्वयं को एक अलग कार्यान्वयन प्रदान करने के लिए उस विधि को ओवरराइड किया था, लेकिन आपको मूल वर्ग द्वारा प्रदान किए गए कार्यान्वयन का आह्वान करने की आवश्यकता है तो आप super कीवर्ड का उपयोग करेंगे। उस स्थिति में, आप super कीवर्ड को छोड़ने का जोखिम नहीं उठा सकते हैं क्योंकि यदि आपने किया तो आप बच्चे वर्ग द्वारा प्रदान किए गए कार्यान्वयन का आह्वान करेंगे।

+0

डाउनवोट? क्यूं कर?डाउनवॉटर, कृपया एक टिप्पणी छोड़ने की देखभाल करें। हो सकता है कि मैं कुछ सीख सकूं। –

+2

यह मैं था! मुझे लगा कि "चाहे आप इसका इस्तेमाल करते हैं या नहीं, इससे कोई फर्क नहीं पड़ता" भ्रामक हो सकता है, खासकर उत्तराधिकारी और ओवरराइड के प्रयासों के मामले में। सच है, आप "इस मामले में" वाक्य को समाप्त कर देते हैं जो इसे कुछ हद तक सटीक बनाता है - लेकिन मुझे अभी भी लगता है कि यह भ्रामक/भ्रमित हो सकता है। इसे दोबारा दोबारा दोहराएं और मैं बिना मतदान के खुश रहूंगा! –

+0

@RichardJPLeGuen: मैंने अपना जवाब दोहराया और भ्रामक हिस्से को हटा दिया। अगर कुछ भी अभी भी भ्रामक है तो मुझे बताएं कि मैं संपादित करने के लिए खुश हूं। टिप्पणी के लिए +1। –

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