objective c इनकम मुझे स्वयं=[सुपर इनिट] क्यों कॉल करना चाहिए




हाल ही में कॉल (5)

मान लें कि मैं अपनी कक्षा और इसकी init विधि बनाते हैं। मुझे स्वयं को सौंपा गया सुपरक्लास init का मूल्य क्यों कॉल करना चाहिए? इसमें कौन से मामले शामिल हैं?

मैं उदाहरणों की सराहना करता हूं कि मुझे कोको सुपरक्लास और गैर-कोको के लिए इसकी आवश्यकता क्यों होगी।


तुम्हारा मतलब है क्यों

self = [super init];

बजाय

[super init];

दो कारण:

  1. प्रारंभिकरण में, विफलता को शून्य लौटने से संकेत मिलता है। आपको पता होना चाहिए कि सुपर ऑब्जेक्ट का प्रारंभिकरण विफल रहा है या नहीं।
  2. सुपर क्लास + ऑलोक द्वारा एक अलग ऑब्जेक्ट के साथ लौटाए गए स्वयं को प्रतिस्थापित करने का विकल्प चुन सकता है। यह दुर्लभ है लेकिन क्लास क्लस्टर के साथ अक्सर होता है।

माइकल की टिप्पणी के जवाब में संपादित:

मैं समझ सकता हूं कि मुझे [सुपर इनिट] को बचाने और वापस करने की आवश्यकता क्यों है। लेकिन क्या यह सिर्फ सम्मेलन है और अच्छी लग रही है कि हम परिणाम को पारित करने के लिए एक अस्थायी चर के रूप में स्वयं का उपयोग करते हैं?

नहीं। इंस्टेंस वैरिएबल को स्वयं पॉइंटर के सापेक्ष एक्सेस किया जाता है, इसलिए निम्न में:

-(id) init
{
    self = [super init];
    if (self != nil)
    {
        myBoolIvar = YES; 
       // The above is an implicit version of self->myBoolIvar = YES;
    }
    return self;
}

स्वयं को स्पष्ट रूप से स्मृति के दाहिने ब्लॉक को इंगित करना है यानी जिसे आप वापस करने जा रहे हैं।

दूसरा मुद्दा यह है कि यदि सुपर इनिट अलग-अलग वर्ग के उदाहरण देता है तो उस लाइन के बाद शेष कोड भी समझ में नहीं आता है, मेमोरी लीक और दुर्घटनाओं का कारण बनता है, उस कक्षा से तुरंत ऑब्जेक्ट के बारे में बात भी नहीं करता है।

यह एक समस्या हो सकती है। अगर मैंने एनएसएनंबर को उप-वर्गीकृत किया और [सुपर इनिट] ने एनएसएसटींग वापस करने का फैसला किया (जो यह कर सकता था - इसे रोकने के लिए कुछ भी नहीं है) जो स्पष्ट रूप से आपदा होगी। -इट से जो भी सुपर रिटर्न इवर्स के लिए जगह प्रदान करने और आगे की अव्यवस्थित होने के अर्थ में सबक्लास के साथ "संगत" होना चाहिए या यह एक भयानक बग है (जब तक, निश्चित रूप से, समस्या दस्तावेज नहीं होती है)। इसलिए, सामान्य रूप से, आपको कक्षा की जांच करने की चिंता करने की आवश्यकता नहीं है। हालांकि, दस्तावेज पढ़ें। उदाहरण के लिए एनएसएसटींग के दस्तावेज़ों में एनएसएसटींग को उपclassing पर अनुभाग देखें।


स्रोत

नामित प्रारंभकर्ता को कार्यान्वित करना

**

स्वयं

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

 return self;  

**

सुपर

** जब हम किसी विधि को ओवरराइड करते हैं, तो हम रखना चाहते हैं कि सुपरक्लास क्या कर रहा है और उस पर आपका सबक्लास कुछ नया जोड़ता है। इसे आसान बनाने के लिए, उद्देश्य-सी नामक सुपर में कंपाइलर निर्देश है। सुपर काम कैसे करता है? आम तौर पर जब आप किसी ऑब्जेक्ट को संदेश भेजते हैं, तो उस नाम की विधि की खोज ऑब्जेक्ट की कक्षा में शुरू होती है। यदि ऐसी कोई विधि नहीं है, तो ऑब्जेक्ट के सुपरक्लास में खोज जारी है। एक उपयुक्त विधि मिलने तक खोज विरासत पदानुक्रम जारी रखेगी। (यदि यह पदानुक्रम के शीर्ष पर पहुंच जाता है और कोई विधि नहीं मिलती है, तो एक अपवाद फेंक दिया जाता है)। जब हम सुपर को संदेश भेजते हैं, तो हम स्वयं को संदेश भेज रहे हैं, लेकिन विधि की खोज ऑब्जेक्ट की कक्षा को छोड़ देती है और सुपरक्लास पर शुरू होती है। उपर्युक्त मामले में, हम सुपर को init संदेश भेजते हैं। यह NSObject की init विधि को कॉल करता है।


क्योंकि आपको ऑब्जेक्ट को किसी भी तरह से प्रारंभ करना है, और संभवतः आप किसी भी प्रारंभिकरण को करना चाहते हैं, एक सुपरक्लास आवश्यक है, क्योंकि आप इससे उतर रहे हैं।


असल में प्रत्येक उद्देश्य-सी वर्ग एक उप-वर्ग है। यह या तो आपके द्वारा निर्दिष्ट कुछ कक्षा या NSObject है।

उपclass (आपकी कक्षा जिस पर आप काम कर रहे हैं) में आप स्वयं = [सुपर init] कहते हैं

यह मूल रूप से क्या करता है सुपर क्लास (जिन्हें मैंने ऊपर बताया है) इनिट विधि (कन्स्ट्रक्टर) कहते हैं और इसे वर्तमान कक्षा में असाइन किया जाता है।

यह सुनिश्चित करता है कि superclasses 'प्रारंभिक विधि कहा जाता है।

अब अगर (स्वयं) के लिए यह मूल रूप से जांचता है कि कोड के उपरोक्त टुकड़े काम करते हैं या नहीं।

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


मुझे पता है कि यह मेरे जवाब के लिए थोड़ा देर हो चुकी है, लेकिन मैं खुद को एक लिंक पोस्ट करने से नहीं रोक सकता जो मुझे इस समस्या के बारे में मेरा संदेह साफ़ करने में बहुत उपयोगी पाया गया।

मैट गैलाघर: जब आप [सुपर इनिट] स्वयं को सौंपते हैं तो इसका क्या अर्थ है?

संपादित करें: टिप्पणियों के अनुसार, लिंक में आवश्यक अंक यहां दिए गए हैं

समझने के लिए क्यों self=[super init]; हमें कई बिंदुओं पर विचार करने की जरूरत है। चलो इसे एक-एक करके निपटें।

self क्या है

प्रत्येक विधि में दो छिपे हुए पैरामीटर होते हैं: self और _cmd । तो विधि कॉल

- (id)initWithString:(NSString *)aString

इस तरह एक फ़ंक्शन कॉल में कंपाइलर द्वारा बदला जाता है

id initWithString(id self, SEL _cmd, NSString *aString);

हमें खुद की आवश्यकता क्यों है?

हकीकत यह है कि संकलक एक विधि के अंदर एक आवृत्ति चर के किसी भी संदर्भ को हल करने के लिए self पैरामीटर का उपयोग करता है।

मान लीजिए कि हमारे पास एक विधि setValueToZero और value उस वर्ग का एक आवृत्ति चर है जो इसके अंतर्गत आता है, फिर कार्यान्वयन

- (void)setValueToZero
{
    value = 0;
}

इस तरह के एक समारोह में संकलक द्वारा परिवर्तित किया जाएगा

void setValueToZero(id self, SEL _cmd)
{
    self->value = 0;
}

जब init को बुलाया जाता है तो क्या पहले से ही एक मूल्य है?

निम्नलिखित एक सामान्य वस्तु निर्माण और प्रारंभिकरण का एक उदाहरण है।

[[MyClass alloc] initWithString:@"someString"]

यहां, जब तक हम initWithString विधि में आते हैं, तब तक स्वयं को आवंटित ऑब्जेक्ट के मूल्य के रूप में (यानी, [MyClass alloc] से वापसी मूल्य) होगा। वास्तव में, यह लगभग सही, अंतिम मूल्य होने की गारंटी है।

क्यों self = [super init]; ?

ऐसा इसलिए है क्योंकि [super init] को तीन चीजों में से एक करने की अनुमति है:

  1. विरासत में प्राप्त उदाहरण मानों के साथ अपना खुद का रिसीवर ( self सूचक नहीं बदलता) लौटाएं।
  2. विरासत में प्राप्त विरासत उदाहरण मानों के साथ एक अलग वस्तु वापस करें।
  3. विफलता का संकेत, रिटर्न nil

पहले मामले में, असाइनमेंट का self पर कोई प्रभाव नहीं पड़ता है। तीसरे मामले में, प्रारंभिक विफल रहा है, self nil सेट है और यह वापस आ गया है।

self को असाइनमेंट के पीछे कारण दूसरे मामले के साथ है। निम्नलिखित को धयान मे रखते हुए

- (id)initWithString:(NSString *)aString
{
    self = [super init];
    if (self)
    {
        instanceString = [aString retain];
    }
    return self;
}

हम से रूपांतरण चाहते हैं

instanceString = [aString retain];

सेवा मेरे

self->instanceString = [aString retain];

सही मूल्य पर कार्य करने के लिए और इस प्रकार हमें self के मूल्य को बदलना होगा।

[super init] एक अलग वस्तु कब वापस होगा?

निम्नलिखित स्थितियों में से एक में

  1. सिंगलटन ऑब्जेक्ट (हमेशा किसी भी आवंटन के बजाय सिंगलटन लौटाता है)
  2. अन्य अनूठी वस्तुओं ( [NSNumber numberWithInteger:0] हमेशा वैश्विक "शून्य" ऑब्जेक्ट देता है)
  3. जब आप सुपरक्लास के उदाहरण को प्रारंभ करते हैं तो क्लास क्लस्टर निजी उप-वर्गों को प्रतिस्थापित करते हैं।
  4. कक्षाएं जो प्रारंभिक में पारित पैरामीटर के आधार पर समान (या संगत) कक्षा को पुन: आवंटित करना चुनती हैं।

अंतिम मामले में, लौटाए गए ऑब्जेक्ट को प्रारंभ करना जारी रखना अगर यह बदलता है तो गलती होती है - लौटाई वस्तु पहले ही पूरी तरह शुरू हो चुकी है और अब आपकी कक्षा से संबंधित नहीं है। तो एक बेहतर init दृष्टिकोण इस प्रकार होगा

- (id)initWithString:(NSString *)aString
{
    id result = [super init];
    if (self == result)
    {
        instanceString = [aString retain];
    }
    return result;
}

निष्कर्ष

अधिकांश वर्गों को काम करने के लिए आपको self को [super init] असाइन करने की आवश्यकता नहीं है। कुछ अस्पष्ट मामलों में, वास्तव में यह करना गलत बात है।

तो हम self को क्यों असाइन करना जारी रखते हैं? यह प्रारंभकर्ता के लिए पारंपरिक टेम्पलेट है, और हालांकि कुछ मामलों में यह गलत है, लेकिन यह अन्य मामलों में सही है जो इस दृष्टिकोण की अपेक्षा करने के लिए लिखे गए हैं।





objective-c