2009-03-25 15 views
29

मुझे लगता है कि चारों ओर कुछ कोड को देखकर किया गया है NSObject के एक प्रोटोकॉल हमले निम्नलिखित जैसा दिखता है?क्यों एक प्रोटोकॉल कार्यान्वयन

id <MyProtocol> foo; // foo here conforms to NSObject AND MyProtocol? 

बस उत्सुक क्या तर्क है: कि बजाय कि में अनावश्यक अगर आप इस तरह के रूप में कुछ कर नहीं है।

उत्तर

27

मुझे पूरा यकीन है कि आप ऐसा करने का कारण एनएसओब्जेक्ट सदस्यों (जैसे कि बनाए रखने और रिलीज़ करना) को अपने प्रोटोकॉल में जोड़ना है। तकनीकी रूप से आप अभी भी उन संदेशों को वैसे भी भेज सकते हैं लेकिन आपको इसके बिना एक कंपाइलर चेतावनी मिल जाएगी।

+2

"तकनीकी रूप से आप अभी भी उन संदेशों को वैसे भी भेज सकते हैं" कोई गारंटी नहीं है कि वस्तु उन संदेशों को समझ जाएगी, अगर आपको नहीं पता कि यह NSObject प्रोटोकॉल लागू करता है। – user102008

+0

यह एक अच्छा पर्याप्त जवाब है –

2

मैंने कभी भी अपने कोड में ऐसा नहीं किया है, लेकिन मैं इसका लाभ देख सकता हूं। यदि आप id <SomeProtocol> के रूप में पैरामीटर पास करते हैं तो आपको उस ऑब्जेक्ट पर किसी भी NSObject के तरीकों को कॉल करना चाहते हैं, तो आपको इसे फिर से डालना होगा।

22

यह बहुत आसान है जब आपके पास ऐसे प्रोटोकॉल हैं जिनमें @optional विधियां हैं (उदाहरण के लिए "आधुनिक" उद्देश्य-सी 2.0 प्रतिनिधि अक्सर इस तकनीक का उपयोग करते हैं) यदि आप NSObject प्रोटोकॉल को शामिल नहीं करते हैं, तो आप चेतावनी प्राप्त करेंगे जब आप कोशिश करेंगे ऑब्जेक्ट पर respondsToSelector: पर कॉल करें।

+5

अच्छा। यह इन दिनों स्वीकार्य उत्तर से अधिक प्रासंगिक है क्योंकि एआरसी किसी को भी बनाए रखने/रिलीज के बारे में चिंता करने की आवश्यकता को हटा देता है। –

31

जब आप घोषित

id<MyProtocol> var; 

ऑब्जेक्टिव-सी संकलक केवल MyProtocol में तरीकों के बारे में जानता है और इस तरह एक चेतावनी का उत्पादन करेगा अगर आप NSObject तरीकों में से किसी को फोन करने की कोशिश की तरह एक चर, जैसे -retain/-release, उस उदाहरण पर। इस प्रकार, कोको NSObject प्रोटोकॉल को परिभाषित करता है जो NSObject वर्ग और आवृत्ति विधियों को प्रतिबिंबित करता है। MyProtocolNSObject प्रोटोकॉल लागू करने से यह घोषणा करते हुए, आप संकलक को एक संकेत देते हैं कि NSObject विधियों को एक उदाहरण द्वारा कार्यान्वित किया जाएगा जो MyProtocol लागू करता है।

यह सब क्यों जरूरी है? उद्देश्य-सी वस्तुओं को किसी भी रूट वर्ग से उतरने की अनुमति देता है। कोको में, एनएसओब्जेक्ट सबसे आम है, लेकिन केवल रूट वर्ग नहीं है। उदाहरण के लिए NSProxy भी एक मूल वर्ग है। इसलिए id प्रकार का उदाहरण आवश्यकNSObject के तरीकों का उत्तराधिकारी है।

+1

आप "NSObject * चर" क्यों नहीं कर सकते? फिर आप जानते हैं कि यह एनएसओब्जेक्ट से लिया गया है लेकिन प्रोटोकॉल के अनुरूप भी है, तो संकलक बनाए रखने और रिलीज करने के बारे में शिकायत नहीं करेगा। – dreamlax

+0

प्रैक्टिक रूप से, यह ठीक है (जैसा कि किसी भी @protocol (NSObject) विधियों का उपयोग करने से पहले (NSObject *) को कास्टिंग कर रहा है। बेशक, उदाहरण वास्तव में, एनएसओब्जेक्ट नहीं है। अधिक महत्वपूर्ण बात यह है कि एनएसओब्जेक्ट प्रोटोकॉल को लागू करने के रूप में मायप्रोटोकॉल घोषित करना स्पष्ट करता है प्रोटोकॉल का इरादा –

+3

यदि आपका प्रोटोकॉल NSObject के अनुरूप नहीं है, तो मुझे इसके बजाय 'id 'का उपयोग करना बेहतर लगता है।एक कारण यह है कि 'आईडी' के साथ गतिशील टाइपिंग आपको किसी भी विधि को कॉल करने की अनुमति देता है, जिसे संकलक एनएसओब्जेक्ट से विरासत में प्राप्त तरीकों के बजाय या आपके प्रोटोकॉल में घोषित किए गए तरीकों के बजाय (चेतावनी के बिना) घोषित कर सकता है। यह भरोसेमंद और अविश्वसनीय रूप से उपयोगी दोनों हो सकता है, इस पर निर्भर करता है कि आप सुरक्षित धारणाएं कर रहे हैं या नहीं। :-) –

2

यदि आप किसी भी NSObject प्रोटोकॉल विधियों जैसे कि बनाए रखने, रिलीज, कक्षा, कक्षा नाम का उपयोग करते हैं, तो संकलक आपको चेतावनी देगा जब तक कि आपके प्रोटोकॉल में NSObject प्रोटोकॉल भी शामिल न हो।

संबंधित मुद्दे