ओवरराइड करते समय सुपर () विधि को कॉल करने के लिए नहीं?


113

जब मैं अपना खुद का एंड्रॉइड कस्टम वर्ग बनाता हूं, तो मैं extendइसका मूल वर्ग हूं । फिर जब मैं आधार विधि ओवरराइड करना चाहते हैं, मैं हमेशा फोन super()विधि, जैसे मैं हमेशा में क्या onCreate, onStopआदि

और मुझे लगा कि यह वही है, क्योंकि शुरुआत से ही एंड्रॉइड टीम ने हमें हमेशा superहर तरीके को ओवरराइड करने की सलाह दी थी ।

लेकिन, कई पुस्तकों में मैं देख सकता हूं कि डेवलपर्स, खुद से अधिक अनुभवी, अक्सर कॉल करने से चूक जाते हैं superऔर मुझे वास्तव में संदेह है कि वे इसे ज्ञान की कमी के रूप में करते हैं। उदाहरण के लिए, इस मूल SAX पार्सर वर्ग को देखें जहां superछोड़ा गया है startElement, charactersऔर endElement:

public class SAXParser extends DefaultHandler{
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }
    }

    public void characters(char[] ch, int start, int length) throws SAXException {
        //do something
    }

    public void endElement(String uri, String localName, String qName) throws SAXException {
        if(qName.equalsIgnoreCase("XXY")) {
            //do something
        }else () {
            //do something
        }
    }
}

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

यह सिर्फ एक सरल उदाहरण था। किताबें समान कोड से भरी होती हैं ।

उन्हें कैसे पता चलेगा कि आपको कब कॉल करना है superऔर कब आप इसे कॉल करना छोड़ सकते हैं?

पुनश्च। इस विशिष्ट उदाहरण से मत बंधिए। यह कई उदाहरणों से बेतरतीब ढंग से उठाया गया एक उदाहरण मात्र था।

(यह एक शुरुआती प्रश्न की तरह लग सकता है, लेकिन मैं वास्तव में भ्रमित हूं।)


3
endElement's एपीआई डॉक कहता है' 'डिफ़ॉल्ट रूप से, कुछ भी न करें। एप्लिकेशन लेखक इस पद्धति को ओवरराइड कर सकते हैं ... "जिसका अर्थ है कि आप सुरक्षित रूप से सुपर कॉल कर सकते हैं क्योंकि यह" कुछ नहीं "करता है लेकिन आपके पास नहीं है और आप इसे वास्तव में ओवरराइड कर सकते हैं। आप अक्सर बता सकते हैं कि क्या आपको उस विधि के लिए डॉक्टर को पढ़ना / करना है या नहीं करना चाहिए।
zapl

1
छोटा उदाहरण: मैं छप स्क्रीन में onBackPressed () का उपयोग करता हूं, और मैं सुपर कॉल नहीं करता हूं, इसलिए यह छप से बाहर नहीं जाता है, यह सिर्फ बटन को निष्क्रिय करता है।
बोजान कोजोज

@sandalone यहां से पूछने के लिए क्षमा करें, लेकिन क्या आपके पास इन-ऐप बिलिंग के साथ वैट टैक्स को संभालने का कोई अनुभव है, और यह Google द्वारा स्वचालित रूप से किन देशों में किया जाता है, और जिन्हें मुझे मैन्युअल रूप से वैट कर / भुगतान करने की रिपोर्ट करनी है? देखें stackoverflow.com/questions/36506835/…
विदर्भ Vestnes

जवाबों:


144

superविधि को कॉल करके , आप विधि के व्यवहार को ओवरराइड नहीं कर रहे हैं, आप इसे बढ़ा रहे हैं ।

किसी कॉल को superउस विधि के लिए परिभाषित किए गए किसी भी तर्क को करने के लिए कॉल करेगा। इस बात को ध्यान में रखें कि यह महत्वपूर्ण हो सकता है जब आप superअपने तरीके के कार्यान्वयन को ओवरराइडिंग कहते हैं। उदाहरण के लिए:

public class A { 
    public void save() { 
         // Perform save logic
    }
}

public class B extends A {
    private Object b;
    @Override
    public void save() { 
        super.save(); // Performs the save logic for A
        save(b); // Perform additional save logic
    }
}

एक कॉल करने के लिए B.save()प्रदर्शन करेंगे save()दोनों के लिए तर्क Aऔर Bइस विशेष क्रम में,। यदि आप फोन नहीं कर रहे थेsuper.save() अंदरB.save() , A.save()तो नहीं बुलाया जाएगा। और अगर आप बुलाया super.save()के बाद save(b), A.save()प्रभावी रूप से बाद में प्रदर्शन किया जा जाएगा B.save()

यदि आप व्यवहार को ओवरराइड करना चाहते superहैं (यानी, इसके कार्यान्वयन को पूरी तरह से अनदेखा करें और इसे स्वयं प्रदान करें), तो आपको कॉल नहीं करना चाहिए super

SAXParserआपके द्वारा प्रदान किए गए उदाहरण में, कार्यान्वयन में DefaultHandler, उन विधियों के लिए केवल खाली हैं, ताकि उपवर्ग उन्हें ओवरराइड कर सकें और उन विधियों के लिए एक व्यवहार प्रदान कर सकें। में जावाडोक इस विधि के लिए यह भी उठाई बाहर है।

public void startElement (String uri, String localName,
    String qName, Attributes attributes) throws SAXException {
    // no op
}

super()आईडीई द्वारा उत्पन्न कोड में डिफ़ॉल्ट कॉल के बारे में , जैसा @barsjuकि उनकी टिप्पणी में बताया गया है, प्रत्येक निर्माता में एक अंतर्निहित कॉल है super()(भले ही आप इसे अपने कोड में न लिखें), जिसका अर्थ है, उस संदर्भ में, एक कॉलsuper 'के ' डिफ़ॉल्ट निर्माता। IDEबस इसे आप के लिए नीचे लिखते हैं, लेकिन यह भी अगर आप इसे हटा दिया बुलाया जायेगा। यह भी ध्यान दें कि जब कंस्ट्रक्टरों को लागू किया जाता है, super()या इसके किसी भी प्रकार के तर्क (यानी super(x,y,z)) को केवल विधि की शुरुआत में कहा जा सकता है ।


14
यह भी ध्यान रखें कि कंस्ट्रक्टरों के लिए super()(सुपर क्लास का डिफ़ॉल्ट कंस्ट्रक्टर) हमेशा कहा जाता है, भले ही आप इसे निर्दिष्ट न करें। यदि सुपर क्लास में डिफॉल्ट कंस्ट्रक्टर नहीं है तो आपको कंप्लेन एरर मिलेगा यदि आप स्पष्ट रूप से सुपर क्लास के कंस्ट्रक्टर्स में से एक को सबक्लास कंस्ट्रक्टर में अपना पहला स्टेटमेंट नहीं कहते हैं।
बारसु

1
हां, यह मूल रूप से सिर्फ आलस्य है - उन तरीकों के लिए जो हम जानते हैं कि कुछ भी नहीं करते हैं केवल संक्षिप्तता के लिए इसे छोड़ दें
Voo

1
आपकी मूल्यवान टिप्पणियों के लिए धन्यवाद, @barjsu, मैंने इन विवरणों को उत्तर में शामिल किया है।
ज़ावी लोपेज़

16

उन्हें कैसे पता चलेगा कि आपको सुपर कब कॉल करना है और आप इसे कब कॉल कर सकते हैं?

आमतौर पर, यदि एक विशेष एपीआई विधि अंतर्निहित ढांचे संदर्भ जीवन चक्र के लिए एक महत्वपूर्ण अर्थ नहीं है, यह हमेशा स्पष्ट रूप से कहा और API दस्तावेज़ों में प्रकाश डाला, जैसे की जाएगी Activity.onCreate()API दस्तावेज़ । इसके अलावा, अगर एपीआई एक मजबूत डिजाइन का अनुसरण करता है, तो उसे परियोजना के संकलन समय पर उपभोक्ता डेवलपर को सचेत करने के लिए कुछ अपवादों को फेंकना चाहिए, और यह सुनिश्चित करना चाहिए कि यह रन समय पर गलती उत्पन्न नहीं करेगा।

यदि यह एपीआई प्रलेखन में स्पष्ट रूप से नहीं कहा गया है, तो उपभोक्ता डेवलपर के लिए यह मानना ​​काफी सुरक्षित है कि एपीआई विधि को ओवरराइड करते समय कॉल करना अनिवार्य नहीं है। यह तय करने के लिए उपभोक्ता डेवलपर पर निर्भर है कि वह डिफ़ॉल्ट व्यवहार का उपयोग करें ( superविधि को कॉल करें ) या इसे पूरी तरह से ओवरराइड करें।

यदि शर्त की अनुमति है (मुझे ओपन-सोर्स सॉफ़्टवेयर पसंद है), उपभोक्ता डेवलपर हमेशा एपीआई स्रोत कोड की जांच कर सकता है और देख सकता है कि वास्तव में कैसे हुड के तहत विधि लिखी गई है। की जाँच करें Activity.onCreate()स्रोत और DefaultHandler.startElement()स्रोत उदाहरण के लिए।


मुझे अतिरिक्त बातें समझाने के लिए धन्यवाद। स्रोत कोड की जांच करने के लिए मुझे याद दिलाने के लिए धन्यवाद।
सैंडलोन

7

आपके सिर में जो परीक्षण करना चाहिए वह है:

"क्या मैं चाहता हूं कि मेरे लिए इस पद्धति की सभी कार्यक्षमता हो, और फिर बाद में कुछ करें?" यदि हाँ, तो आप कॉल करना चाहते हैं super(), और फिर अपनी विधि समाप्त करें। यह "महत्वपूर्ण" विधियों के लिए सही होगा onDraw(), जैसे कि पृष्ठभूमि में बहुत सी चीजें संभालती हैं।

यदि आप केवल कुछ कार्यक्षमता चाहते हैं (अधिकांश विधियों के साथ जिन्हें आप ओवरराइड करेंगे) तो आप शायद कॉल नहीं करना चाहते हैं super()


3

खैर ज़ावी ने बेहतर जवाब दिया .. लेकिन आप शायद जान रहे होंगे कि क्या करता हैsuper() ओवरराइड पद्धति में कॉल करने पर है ... यह विज्ञापन करता है कि आपने डिफ़ॉल्ट व्यवहार के साथ क्या किया है।

उदाहरण के लिए:

onDraw() 

जब ओवरराइड किया जाता है तो व्यू क्लास में विधि। आप सुपर होने से पहले कुछ आकर्षित करते हैं। (यह दृश्य पूरी तरह से तैयार superहो जाने के बाद दिखाई देता है .. इसलिए यहां कॉलिंग आवश्यक है क्योंकि एंड्रॉइड के लिए कुछ महत्वपूर्ण महत्वपूर्ण चीजें हैं (जैसे onCreate ())

लेकिन उसी समय पर

onLongClick()

जब आप इसे ओवरराइड करते हैं तो आप सुपर को कॉल नहीं करना चाहते हैं क्योंकि यह एक एडिटटेक्स्ट या किसी अन्य समान दृश्य के लिए विकल्पों की सूची के साथ एक संवाद लाता है .. यह मूल अंतर है .. आपके पास इसे कुछ समय छोड़ने का विकल्प है .. लेकिन इसके लिए onCreate() , onStop()आप की तरह अन्य तरीकों को ओएस को संभालने देना चाहिए।


2

मुझे आपका प्रश्न स्पष्ट रूप से नहीं मिला, लेकिन यदि आप इस बारे में पूछ रहे हैं कि superविधि को क्यों नहीं कहा जाए :

superविधि को कॉल करने का एक कारण है : यदि मूल कक्षा में कोई शून्य तर्क निर्माता नहीं है, तो उसके लिए एक बाल वर्ग बनाना संभव नहीं है, इसलिए या तो आपको मूल कक्षा में कोई तर्क निर्माता रखने की आवश्यकता है या आपको आवश्यकता है चाइल्ड क्लास कंस्ट्रक्टर के शीर्ष पर super()कॉलिंग स्टेटमेंट को परिभाषित करना argument(how much argument constructor you have used in super class)

आशा है कि ये आपकी मदद करेगा। यदि नहीं, तो मुझे बताएं।


2

मैंने एक बाधा सरणी सूची को लागू किया

public class ConstraintArrayList<T> extends ArrayList<T> {
  ConstraintArrayList(Constraint<T> cons) {this.cons = cons;}
  @Override
  public boolean add(T element) {
    if (cons.accept(element))
      return super.add(element);
    return false;
  }
}

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

  1. जहाँ आप सुपर क्लास क्या कर सकते हैं, इसका विस्तार करना चाहते हैं
  2. विशिष्टता जहाँ आप बहुरूपता के माध्यम से विशिष्ट व्यवहार जोड़ना चाहते हैं जैसे कि सामान्य पशु राज्य में चाल शब्दार्थ का उदाहरण जहाँ पक्षी चलते हैं (उड़ते हैं) और मेंढक चलते हैं (हॉप) प्रत्येक उप वर्ग के लिए विशिष्ट होते हैं।

2

उन लोगों के लिए जो यह भी सोचते हैं कि एंड्रॉइड फ्रेमवर्क से कौन से ओवरराइड तरीके हैं, उन्हें कॉल करना चाहिए superऔर यह सवाल मिला - यहां 2019 से एक वर्तमान संकेत है - एंड्रॉइड स्टूडियो 3+ आपको बताएगा कि आपको कब इसकी आवश्यकता है

यहां छवि विवरण दर्ज करें

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.