2012-04-20 11 views
101

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

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

लेकिन, कई किताबें में मैं देख सकता हूँ कि डेवलपर्स, अपने आप की तुलना में अधिक अनुभवी अक्सर super बुला छोड़ देते हैं और मैं वास्तव में संदेह है कि वे ज्ञान की कमी के रूप में करते हैं।

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 हमेशा एक रूप में बनाया जाएगा: उदाहरण के लिए, इस बुनियादी SAX पार्सर वर्ग जहां superstartElement, characters और endElement में छोड़ दिया जाता है पर देखने के स्वचालित प्रक्रिया का हिस्सा।

यह एक साधारण उदाहरण था। किताबें समान कोड से भरे हुए हैं।

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

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

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

+3

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

+1

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

+0

@ सैंडलोन यहां पूछने के लिए खेद है, लेकिन क्या आपको इन-ऐप बिलिंग के साथ वैट टैक्स को संभालने के तरीके पर कोई अनुभव है, और यह किन देशों को Google द्वारा स्वचालित रूप से किया जाता है, और मुझे वैट टैक्स को मैन्युअल रूप से रिपोर्ट/भुगतान करना पड़ता है? http://stackoverflow.com/questions/36506835/android-in-app-billing-vat-tax –

उत्तर

130

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() को एक कॉल इस विशेष क्रम में, A और B दोनों के लिए save() तर्क प्रदर्शन करेंगे। यदि आप को B.save() के अंदर नहीं बुला रहे थे, A.save() नहीं कहा जाएगा। और यदि आपने को save(b) के बाद बुलाया, A.save() प्रभावी ढंग से B.save() के बाद प्रभावी ढंग से प्रदर्शन किया जाएगा।

अगर आप चाहते हैं ओवरराइडsuper के व्यवहार (कि, पूरी तरह से इसके कार्यान्वयन पर ध्यान न दें और यह सब अपने आप को प्रदान किया जाता है) के लिए, आप super नहीं बुला जाना चाहिए। ताकि उपवर्गों उन्हें ओवरराइड और उन तरीकों के लिए एक व्यवहार प्रदान कर सकते हैं

SAXParser उदाहरण उपलब्ध कराने में, उन तरीकों के लिए DefaultHandler की implementations, बस खाली हैं। इस विधि के लिए javadoc में यह भी इंगित किया गया है।

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

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

+14

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

+1

हां, यह मूल रूप से केवल आलस्य है - जिन विधियों के बारे में हम जानते हैं, वे कुछ भी नहीं करते हैं, बस इसे ब्रेवटी – Voo

+1

के लिए छोड़ दें अपनी बहुमूल्य टिप्पणियों के लिए धन्यवाद, @barjsu, मैंने इन विवरणों को उत्तर में शामिल किया है। –

3

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

जैसे में कहा जाता है क्या करता है :

onDraw() 

जब अधिरोहित दृश्य कक्षा में विधि .. आप कुछ super.onDraw (कह से पहले) आकर्षित ऐसा लगता है एक बार देखने के लिए पूरी तरह से तैयार है .. इसलिए यहाँ बुला super आवश्यक है के बाद से एंड्रॉयड के लिए कुछ गंभीर रूप से महत्वपूर्ण बातें है करें (ऑनक्रेट())

लेकिन एक ही समय में

onLongClick() 

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

2

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

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

मुझे उम्मीद है कि इससे मदद मिलती है। यदि नहीं, तो मुझे बताएं।

7

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

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

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

15

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

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

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

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

+0

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

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. तानाना चलने वाले अर्थशास्त्र का साम्राज्य उदाहरण जहां पक्षियों को स्थानांतरित करना (उड़ना) और मेंढक चलाना (हॉप) प्रत्येक उप वर्ग के लिए विशिष्ट हैं।