नए के बजाय आवंटन init का उपयोग


344

उद्देश्य-सी सीखना और नमूना कोड पढ़ना, मुझे लगता है कि इस पद्धति का उपयोग करके आमतौर पर ऑब्जेक्ट बनाए जाते हैं:

SomeObject *myObject = [[SomeObject alloc] init];

के बजाय:

SomeObject *myObject = [SomeObject new];

क्या इसका कोई कारण है, जैसा कि मैंने पढ़ा है कि वे समान हैं?


12
मुझे पता भी नहीं था कि यह संभव था! सभी सामग्री जो मैंने पढ़ी है वह दिखाती है जैसे नया कीवर्ड मौजूद नहीं है!
जोनाथन

78
वास्तव में "नया" ऑब्जेक्टिव-सी में एक कीवर्ड नहीं है, लेकिन NSObject एक क्लास मेथड "नया" लागू करता है, जिसे बस "एलोक" और "इनिट" कहते हैं।
डॉन मैककॉघे

3
जोनाथन, यही मेरे सवाल का संकेत देता है। वे कार्यात्मक रूप से समकक्ष हो सकते हैं लेकिन [[आवंटन] init] स्पष्ट रूप से प्रमुख मुहावरा है।
विच 2

1
मुझे लगता है कि Apple (उनके आईट्यून्स स्टैनफोर्ड व्याख्यानों में से एक से जो मैं याद कर सकता हूं) सिर्फ आपको इसके बदले आवंटन का उपयोग करने के लिए प्रोत्साहित करता है ताकि आप क्या हो रहा है की प्रक्रिया को समझ सकें। वे अपने नमूना कोड में नए का उपयोग नहीं करते हैं, इसलिए आवंटित init सिर्फ एक सामान्य अच्छी आदत है जिसे Apple बढ़ावा देने की कोशिश करता है।
पोस्टकोडवाद

जवाबों:


290

यहाँ कारणों का एक गुच्छा है: http://macresearch.org/difference-between-alloc-init-and-new

कुछ चुने हुए हैं:

  • newकस्टम आरंभीकरण का समर्थन नहीं करता (जैसे initWithString)
  • alloc-init से अधिक स्पष्ट है new

आम राय यह लगती है कि आपको जो भी सहज हो उसका उपयोग करना चाहिए।


8
यदि आपका वर्ग निर्दिष्ट इनिशियलाइज़र के रूप में उपयोग करता है, तो + नया उसे कॉल करेगा। जेरेमी क्या बात कर रहा है, अगर आपके पास एक कस्टम इनिशलाइज़र है जो कि नहीं है। -initWithName:, उदाहरण के लिए।
bbum

87
कुछ भी नहीं है जो आपको लागू करने से रोकता है +newWithString:, यदि आप पहले से ही लागू हैं -initWithString। हालांकि यह आम नहीं है। व्यक्तिगत रूप से मैं हमेशा उपयोग करता हूं newजब निर्दिष्ट इनिशियलाइज़र होता है init, बस सू छोटा और मीठा होता है।
PeyloW

11
मुझे पता है कि यह एक पुराना धागा है, लेकिन मैं सिर्फ इस बात पर जोर देना चाहता हूं कि आपको लागू नहीं करना चाहिए+newWithString: । इससे चिंताओं का अलगाव टूट जाता है। जब आप बस किसी -initभी तरह का उपयोग करना चाहते हैं , तो कोई कारण नहीं है कि बस का उपयोग न करें +new, हालांकि।
जोनाथन स्टर्लिंग

7
@JonathanSterling: Apple के पास कई उदाहरण हैं जहां वे ठीक वही काम करते दिखाई देते हैं जिसके खिलाफ आप सलाह देते हैं; उदाहरण के लिए [[NSString alloc] initWithFormat:...]और [NSString stringWithFormat:...]दोनों समान हैं। क्या आप कह रहे हैं कि Apple ने चिंताओं को अलग करने का उल्लंघन किया है और इसे इस तरह लागू नहीं करना चाहिए था? (ध्यान दें: मैं कृपालु होने की कोशिश नहीं कर रहा हूं; मैं सिर्फ अधिक जानकारी प्राप्त करना चाहूंगा, और जान सकता हूं कि क्या एप्पल की लीड का अनुसरण करना एक बुरा विचार है।)
सेंसफुल

6
मेरा मानना ​​है कि एआरसी (या कचरा संग्रह) से पहले के दिनों की तारीखें हैं। वे दो चीजें जो हम समतुल्य नहीं हैं। stringWithFormat: आबंटित करते समय एक ऑटोरेल्ड स्ट्रिंग लौटाएगा: init: मैन्युअल रूप से जारी या ऑटोरेल्ड होने की आवश्यकता होगी, अन्यथा यह मेमोरी लीक का कारण होगा।
19

139

बहुत पुराना सवाल है, लेकिन मैंने कुछ उदाहरण सिर्फ मनोरंजन के लिए लिखे हैं - शायद आपको यह उपयोगी लगे;)

#import "InitAllocNewTest.h"

@implementation InitAllocNewTest

+(id)alloc{
    NSLog(@"Allocating...");
    return [super alloc];
}

-(id)init{
    NSLog(@"Initializing...");
    return [super init];
}

@end

मुख्य समारोह में दोनों कथन:

[[InitAllocNewTest alloc] init];

तथा

[InitAllocNewTest new];

एक ही उत्पादन में परिणाम:

2013-03-06 16:45:44.125 XMLTest[18370:207] Allocating...
2013-03-06 16:45:44.128 XMLTest[18370:207] Initializing...

5
बहुत बढ़िया जवाब! बस यह जोड़ना चाहते हैं कि + नया प्रयोग उन मामलों के लिए बहुत अच्छा है, जहाँ आपको केवल उपयोग करने की आवश्यकता है और कुछ भी अधिक विशिष्ट -initWithSomething जैसा नहीं: ...
cgossain

दुर्भाग्य से, यह उदाहरण प्रमाण नहीं है कि वे समान हैं। यह सिर्फ एक उदाहरण है जहां वे एक ही परिणाम उत्पन्न करते हैं।
विंस ओ'सुलीवन

10
दुर्भाग्य से, यह उदाहरण प्रमाण नहीं है कि वे समान हैं। यह सिर्फ एक उदाहरण है जहां वे होते हैं वही परिणाम उत्पन्न करते हैं। दूसरी ओर, यह साबित करता है कि वे अलग-अलग हैं ... ऊपर दिए गए उदाहरण को लेते हुए, "InitAllocNewTest.h" को निम्नानुसार संशोधित करें: @interface InitAllocNewTest: NSObject - (instancypeype) __unavailable init; @end अप्रभावित रहते [[InitAllocNewTest alloc] init]हुए संकलन नहीं करेगा [InitAllocNewTest new]। (लाइन ब्रेक की कमी के लिए माफी, आदि)
विंस ओ'सूलीवन

1
@ विंसो सुलिवन, अच्छी बात है। इसका मतलब यह है कि यदि कोई इनलेट अनुपलब्ध बनाना चाहता है, जैसे कि एकल वर्ग में, किसी को नए को भी अक्षम करना चाहिए। मैं यहां यह नहीं बताऊंगा कि एकल गीत अच्छे हैं या बुरे।
user3099609

उपरोक्त कोड से मेरा एक प्रश्न है। क्यों "वापसी [सुपर init]?" आम तौर पर init एक ऐसा तरीका है जहाँ कक्षा के सदस्यों को आरंभीकृत किया जाता है, क्यों सूचक परिवर्तन बहुत अजीब है!
पृथ्वीवीर राव नादौनुरू

52

+new+alloc/-initएप्पल के NSObjectकार्यान्वयन के बराबर है । यह बहुत संभावना नहीं है कि यह कभी भी बदल जाएगा, लेकिन आपके व्यामोह के स्तर के आधार पर, +newभविष्य में कार्यान्वयन के परिवर्तन (और समतुल्यता को तोड़ने) के लिए Apple के दस्तावेज प्रकट होते हैं। इस कारण से, क्योंकि "स्पष्ट निहितार्थ से बेहतर है" और ऐतिहासिक निरंतरता के लिए, उद्देश्य-सी समुदाय आमतौर पर बचता है +new। हालांकि, आप आमतौर पर ऑब्जेक्टिव-सी करने के लिए हाल ही में जावा से आने वालों के अपने हठी प्रयोग के द्वारा देखा जा सकता है +new


8
यद्यपि यह अक्सर सच होता है, साथ ही साथ उबाऊपन के पक्ष में एक शिविर भी होता है, जिसमें केवल स्पष्ट होने पर और स्पष्ट होने पर चिंता का विषय होता है।
पीटर डेविस

27
मैंने इसे +newकम कर दिया क्योंकि NeXT के दिनों से यह चारों ओर है। अगर कुछ भी +newकिसी की निशानी के बारे में कुछ है जो बहुत पहले से सीखा है; मैं ऐसे बहुत से लोगों को देखता हूं जो भाषा में नए सिरे से आते हैं, या जो सालों से इसे लिख रहे हैं, लेकिन स्पष्ट रूप से iOS बूम के बाद, इसका कोई +newमतलब नहीं है। दूसरा, जैसा +newकि बहुत पुराना है और NeXT के दिनों से, Apple इसे एक तरह से बदलने के लिए बहुत ही पागल होगा, जो पुराने कोड को तोड़ता है, विशेष रूप से अपने स्वयं के कोड आधारों को देखते हुए शायद इसके साथ अटे पड़े हैं।
आसवीकौ

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

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

7
मैं वास्तव में कल्पना नहीं कर सकता कि क्यों एक समाधान जहां आपको टाइप करना है और अधिक पसंद किया जाएगा (init आवंटित करें), विशेष रूप से ऑब्जेक्टिव-सी जैसे क्रियात्मक भाषा में जहां कीस्ट्रोक्स को बचाने से आपको समय की बचत होगी। वे "डॉग्ड जावा डेवलपर्स" सिर्फ अपने विश्लेषणात्मक कौशल का उपयोग अनावश्यक रूप से टाइप करने वाले अतिरिक्त वर्ण लिखने के बजाय कम समय लिखने वाले कोड को खर्च करने के लिए कर रहे हैं जो समान कार्यात्मक परिणाम उत्पन्न करते हैं।
२१

9

अक्सर, आपको तर्कों को पास करने की आवश्यकता होती है initऔर इसलिए आप एक अलग विधि का उपयोग करेंगे, जैसे कि [[SomeObject alloc] initWithString: @"Foo"]। यदि आप इसे लिखने के आदी हैं, तो आपको इसे इस तरह से करने की आदत है और इसलिए [[SomeObject alloc] init]यह स्वाभाविक रूप से अधिक हो सकता है [SomeObject new]


7

एक लघु उत्तर है:

  1. दोनों समान हैं। परंतु
  2. 'नया' केवल मूल 'init' इनिशलाइज़र के साथ काम करता है, और अन्य इनिशियलाइज़र (जैसे initWithString :) के साथ काम नहीं करेगा।

3

एक साइड नोट के लिए, मैं व्यक्तिगत रूप से उपयोग करता [Foo new]हूं अगर मैं चाहता हूं कि कुछ भी इनिट का उपयोग किए बिना किया जाए तो यह कहीं भी रिटर्न वैल्यू नहीं है। अगर आपने [[Foo alloc] init]कहीं भी रिटर्न का इस्तेमाल नहीं किया तो आपको चेतावनी मिल जाएगी। कम या ज्यादा, मैं [Foo new]आंख कैंडी के लिए उपयोग करता हूं ।


3

मुझे इसमें बहुत देर हो गई है लेकिन मैं यह उल्लेख करना चाहता हूं कि स्विफ्ट की दुनिया के साथ ओज-सी में यह वास्तव में असुरक्षित है। स्विफ्ट केवल एक डिफ़ॉल्ट init पद्धति बनाएगी यदि आप कोई अन्य इनिशियलाइज़र नहीं बनाते हैं। कस्टम इनिलाइज़र के साथ एक स्विफ्ट क्लास पर नया कॉल करने से क्रैश हो जाएगा। यदि आप आवंटित / init का उपयोग करते हैं तो कंपाइलर ठीक से शिकायत करेगा कि init मौजूद नहीं है।


1

यदि नया आपके लिए काम करता है, तो यह आपके कोड को मामूली रूप से छोटा कर देगा। यदि आप अन्यथा [[SomeClass alloc] init]अपने कोड में कई अलग-अलग स्थानों पर कॉल करेंगे, तो आप नए कार्यान्वयन में एक हॉट स्पॉट बनाएंगे - अर्थात, objc रनटाइम में - जिससे आपके कैश मिस की संख्या कम हो जाएगी।

मेरी समझ में, यदि आपको एक कस्टम इनिशियलाइज़र उपयोग करने की आवश्यकता है [[SomeClass alloc] initCustom]

यदि आप नहीं करते हैं, का उपयोग करें [SomeClass new]


1
मैं "अगर आपको एक कस्टम इनिशियलाइज़र का उपयोग करने की आवश्यकता है तो [[SomeClass आवंटित] initCustom] का उपयोग करने की आवश्यकता होगी"। यदि आपको किसी भी पैरामीटर के बिना एक कस्टम इनिलाइज़र की आवश्यकता है, तो कभी भी ऐसा कुछ न करें जैसा आप सुझाव दे रहे हैं, बस डिफ़ॉल्ट initफ़ंक्शन को ओवरराइड करें और इसका उपयोग करें [[SomeClass alloc] init];यदि आपको मापदंडों की आवश्यकता है, तब भी कभी ऐसा कुछ न करें, ऐसा करें [[SomeClass alloc] initWith:...];। अंत में, यदि आप initकस्टम कार्यान्वयन के साथ फ़ंक्शन को ओवरराइड करते हैं, तो आप newऑब्जेक्ट बनाने पर कॉल कर सकते हैं , और यह अभी भी कस्टम initकार्यान्वयन को कॉल करेगा ।
गंदा 25
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.