सुपर क्लास को कॉल करने के लिए व्युत्पन्न वर्ग को कैसे बाध्य किया जाए? (जैसा आप चाहते हैं)


85

मैं सोच रहा था, जब नई Activityकक्षाएं बना रहा हूं और फिर onCreate()विधि को ओवरराइड कर रहा हूं, तो ग्रहण में मुझे हमेशा ऑटो जोड़ा जाता है super.onCreate():। यह कैसे होता है? क्या अमूर्त या मूल वर्ग में कोई जावा कीवर्ड है जो इसे मजबूर करता है?

मुझे नहीं पता कि क्या सुपर क्लास को कॉल करना गैरकानूनी है, लेकिन मुझे कुछ तरीकों में याद है कि मुझे ऐसा नहीं करने के लिए एक अपवाद मिला। क्या यह भी जावा में निर्मित है? क्या आप ऐसा करने के लिए कुछ कीवर्ड का उपयोग कर सकते हैं? या यह कैसे किया जाता है?


मैं यह भी जानना चाहता हूं। और यह सिर्फ एक्लिप्स के सहायक नहीं है, अगर मैं कॉल को super.onCreate () में हटा देता हूं, तो ऐप यह कहते हुए रनटाइम त्रुटि देता है: "super.onCreate ()" को कॉल नहीं किया। तो हाँ, यह वास्तव में आपको सुपर विधि को कॉल करने के लिए मजबूर कर रहा है। पर कैसे?
रॉड्रिगो कास्त्रो

@RodrigoCastro आप प्रत्येक विधि के लिए javadocs की समीक्षा कर सकते हैं। उदाहरण के लिए OnCreate ()

जवाबों:


10

यहाँ का स्रोत है Activity#onCreate()- यह लगभग सभी टिप्पणियाँ हैं ( मूल - पंक्ति देखें ~ 800 ):

/**
 * Called when the activity is starting.  This is where most initialization
 * should go: calling {@link #setContentView(int)} to inflate the
 * activity's UI, using {@link #findViewById} to programmatically interact
 * with widgets in the UI, calling
 * {@link #managedQuery(android.net.Uri , String[], String, String[], String)} to retrieve
 * cursors for data being displayed, etc.
 *
 * <p>You can call {@link #finish} from within this function, in
 * which case onDestroy() will be immediately called without any of the rest
 * of the activity lifecycle ({@link #onStart}, {@link #onResume},
 * {@link #onPause}, etc) executing.
 *
 * <p><em>Derived classes must call through to the super class's
 * implementation of this method.  If they do not, an exception will be
 * thrown.</em></p>
 *
 * @param savedInstanceState If the activity is being re-initialized after
 *     previously being shut down then this Bundle contains the data it most
 *     recently supplied in {@link #onSaveInstanceState}.  <b><i>Note: Otherwise it is null.</i></b>
 *
 * @see #onStart
 * @see #onSaveInstanceState
 * @see #onRestoreInstanceState
 * @see #onPostCreate
 */
protected void onCreate(Bundle savedInstanceState) {
    mVisibleFromClient = !mWindow.getWindowStyle().getBoolean(
            com.android.internal.R.styleable.Window_windowNoDisplay, false);
    mCalled = true;
}

इसलिए, मेरा अनुमान है कि ADT एक्लिप्स प्लगइन वह है जो super.onCreate()आपके लिए उस कॉल को स्वतः जोड़ने वाला है । हालांकि यह कुल अनुमान है।


2
मुझे लगता है कि यह mCalled = trueभी एक संभावित अपवाद के लिए प्रयोग किया जाता है। शायद नहीं, onCreate()लेकिन जब वास्तव में इस तरह के अपवाद को फेंक दिया जाता है तो यह उस सरल पैटर्न का उपयोग करेगा।
पीटरडक

192

यह समर्थन एनोटेशन लाइब्रेरी में जोड़ा गया है:

dependencies {
    compile 'com.android.support:support-annotations:22.2.0'
}

http://tools.android.com/tech-docs/support-annotations

@CallSuper


हाँ, तुम यहाँ सिर पर कील ठोकते हो। धन्यवाद।
SMBiggs

अभी तक कोशिश नहीं की है लेकिन प्रलेखन पढ़ें। यह मुझे लगता है कि भयानक होने जा रहा है। यह स्वीकृत उत्तर होना चाहिए।
रिजवान सोहैब

1
अन्य सभी उत्तर पूरी तरह से बकवास हैं, सिवाय इसके। स्वीकार किया जाना चाहिए।
Le_Enot

3
@RizwanSohaib यह आपको कुछ भी करने के लिए मजबूर नहीं करेगा। यह उजागर करेगा और आपको बताएगा कि आपको इसे कॉल करने की आवश्यकता है। अधिक जटिल कुछ भी करने के लिए, आपको एनोटेशन प्रोसेसर की आवश्यकता होगी या तर्क को स्वयं लागू करने के लिए। आईडीई के आधार पर, यह आपको निर्माण करने से भी रोकता है।
ठंढाईदार २ '

1
एकदम सही जवाब। बहुत बहुत धन्यवाद
V a Quang Hòa

82

यदि आप मूल वर्ग के तर्क को निष्पादित करने के लिए उपवर्गों को बाध्य करना चाहते हैं , तो एक सामान्य पैटर्न निम्नलिखित जैसा है:

public abstract class SuperClass implements SomeInterface
{
    // This is the implementation of the interface method
    // Note it's final so it can't be overridden
    public final Object onCreate()
    {
        // Hence any logic right here always gets run
        // INSERT LOGIC

        return doOnCreate();

        // If you wanted you could instead create a reference to the
        // object returned from the subclass, and then do some
        // post-processing logic here
    }

    protected abstract Object doOnCreate();
}

public class Concrete extends SuperClass
{
    @Override
    protected Object doOnCreate()
    {
        // Here's where the concrete class gets to actually do
        // its onCreate() logic, but it can't stop the parent
        // class' bit from running first

        return "Hi";
    }
}

यह वास्तव में आपके सवाल का जवाब नहीं देता है कि ग्रहण में स्वचालित रूप से सुपरक्लास कॉल को सम्मिलित करने के लिए क्या संकेत देता है; लेकिन फिर मुझे नहीं लगता कि यह वैसे भी जाने का रास्ता है क्योंकि इसे हमेशा हटाया जा सकता है।

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


8

यदि आप पूरी तरह से सुनिश्चित करना चाहते हैं कि सुपरक्लास-विधि को भी कहा जाए, तो आपको थोड़ा मुश्किल होना चाहिए: सुपरक्लास-विधि को अधिलेखित करने की अनुमति न दें, लेकिन क्या यह एक अतिरक्षित संरक्षित विधि है।

class Super
{
   public final void foo() {
      foo_stuff();
      impl_stuff();
   }

   protected void impl_stuff() {
      some_stuff_that_you_can_override();
   }
}

class Base extends Super
{
  protected void impl_stuff() { 
     my_own_idea_of_impl();
  }
}

इस तरह, उपयोगकर्ता को Super.foo () या Base.foo () कॉल करना होगा और यह हमेशा बेस-क्लास संस्करण होगा क्योंकि इसे अंतिम रूप दिया गया था। कार्यान्वयन-विशिष्ट सामग्री impl_stuff () में है, जिसे ओवरराइड किया जा सकता है।


8

आपके वास्तविक प्रश्न का उत्तर देने के लिए, कॉल का ऑटो-निर्माण super.onCreate () ADT प्लगइन की एक विशेषता है। जावा में, आप सीधे उप-विधि को किसी विधि के सुपर कार्यान्वयन को लागू करने के लिए बाध्य नहीं कर सकते हैं, अफिक (कार्य के चारों ओर अन्य उत्तरों में वर्णित पैटर्न देखें)। हालांकि, ध्यान रखें कि एंड्रॉइड में, आप सीधे गतिविधि ऑब्जेक्ट (या सेवा ऑब्जेक्ट) को इंस्टेंट नहीं कर रहे हैं - आप सिस्टम के लिए एक उद्देश्य पास करते हैं और सिस्टम ऑब्जेक्ट को चालू करता है और उस पर onCreate () और अन्य जीवनचक्र विधियों के साथ कॉल करता है। तो सिस्टम में गतिविधि उदाहरण के लिए एक प्रत्यक्ष वस्तु संदर्भ है और कुछ बूलियन की जांच करने में सक्षम है (संभवतः) जो ऑनक्रिएट () के सुपरक्लास कार्यान्वयन में सही है। हालाँकि मुझे नहीं पता कि इसे कैसे लागू किया जाता है, यह संभवतः कुछ इस तरह दिखता है:

class Activity
{
  onCreate()
  {
    superCalled = true;
    ...
  }
  ...
}

और "सिस्टम" स्तर के वर्ग में जो आशय प्राप्त करता है और उससे गतिविधि ऑब्जेक्ट को तात्कालिक करता है:

...
SomeActivitySubclass someActivitySubclassObject = new SomeActivitySubclass();
someActivitySubclassObject.onCreate();
if (!someActivityObject.isSuperCalled())
{
  Exception e = new Exception(...) //create an exception with appropriate details
  throw e;
}

मेरा अनुमान है कि यह शायद उससे थोड़ा अधिक जटिल है, लेकिन आपको यह विचार मिलता है। ग्रहण स्वचालित रूप से कॉल बनाता है क्योंकि ADT प्लगइन इसे एक सुविधा के रूप में बताता है। हैप्पी कोडिंग!


4

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


3

ग्रहण केवल सहायक हो रहा है, आपको याद दिलाता है कि आप चाहें तो सुपरक्लास कार्यान्वयन को कॉल कर सकते हैं।

आपको शायद एक त्रुटि मिल रही है क्योंकि आप कुछ आवश्यक नहीं कर रहे हैं जो सुपरक्लास करता है, क्योंकि आप इसके कार्यान्वयन को नहीं कह रहे हैं।


1

ग्रहण आपको सही काम करने में मदद करता है और अपवादों से बचता है।

से http://developer.android.com/reference/android/app/Activity.html#onCreate(android.os.Bundle )

व्युत्पन्न वर्गों को सुपर क्लास के इस पद्धति के कार्यान्वयन के माध्यम से कॉल करना होगा। यदि वे नहीं करते हैं, तो एक अपवाद फेंक दिया जाएगा।

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