self
एक बहुरूपी कक्षा उदाहरण के रूप में एक वर्ग विधि में इस्तेमाल किया जा सकता है।
इसलिए वर्ग विधि new
इस तरह लागू किया जा सकता:
+ (id)new
{
return [[self alloc] init];
}
और कक्षा उदाहरण है कि संदेश भेजा है के लिए सही प्रकार वापसी होगी:
पूर्व एक:
NSArray * a = [NSArray new]; // << a is an NSArray
पूर्व बी:
NSMutableArray * a = [NSMutableArray new]; // << a is an NSMutableArray
नीचे नोट देखें।
तो आपको वास्तव में क्या सामना करना पड़ रहा है यह सुनिश्चित करना है कि प्रोटोकॉल में केवल उदाहरण विधियां हैं, और वह (वर्ग) स्वयं के तरीकों प्रोटोकॉल में उदाहरण विधियों को अपनाने के लिए मानचित्रण करते हैं।
जहां तक डिज़ाइन ... अच्छा है, मान लीजिए कि मैं इसे इस तरह से नहीं लिखूंगा। एक सिंगलटन स्पष्ट और अधिक सही होता, लेकिन मुझे सिंगलेट्स भी पसंद नहीं आया, इसलिए मैं उस मार्ग को नहीं लेता।
चेतावनी उत्पादन किया जाता है क्योंकि कक्षा उदाहरण (क्या पारित हो जाता है) @protocol
delegate
पैरामीटर द्वारा निर्दिष्ट अपनाने है। Class
उदाहरण वर्ग का उदाहरण नहीं है। एक प्रोटोकॉल घोषणा वास्तव में कक्षा के उदाहरण पर लागू होती है। उदाहरण के लिए, यदि आप NSLocking
अपनाते हैं, तो क्या संकलक आपको प्रोटोकॉल में घोषित प्रत्येक इंस्टेंस विधि के लिए क्लास विधियों को लागू करने की अपेक्षा करता है? उत्तर: कभी नहीं। जिस कार्यान्वयन के साथ आप काम कर रहे हैं वह आईएमओ उन मामलों में से एक है जहां यह भाषा का दुरुपयोग है, लेकिन यह काम करने के लिए होता है।
शब्दावली स्पष्ट करने के लिए:
"Class
उदाहरण" एक वर्ग विधि में self
है:
- (void)foo { self; }
:
+ (void)foo { self; }
एक "वर्ग के उदाहरण" एक उदाहरण विधि में self
है
अभ्यास में, -[NSObject conformsToProtocol:]
+[NSObject conformsToProtocol:]
और +[NSObject class]
बसदेता हैइसलिए निष्पादन में कोई त्रुटि नहीं है।
मैं अभी भी स्पष्ट नहीं हूं, फिर, मुझे चेतावनी क्यों मिल रही है, यदि कोड आपके द्वारा वर्णित मानदंडों को पूरा करता है।
मापदंड मैं वर्णित निष्पादन पर लागू होता है, लेकिन यह भाषा के शब्दों से भटक - इस प्रकार, संकलक इस पर पूरी तरह से सही है।
समस्या के लिए एक समाधान के लिए: वहाँ कोई रास्ता नहीं संकलक "मेरी क्लास उदाहरण प्रोटोकॉल के अनुरूप है" बताने के लिए क्योंकि गोद लेने की घोषणा वर्ग की उदाहरणों पर लागू होता है है।
साफ, सही दृष्टिकोण: वर्ग का एक उदाहरण का उपयोग करें और के रूप में परिभाषित प्रोटोकॉल लागू
आप दो प्राथमिक विकल्प हैं।
या प्रोटोकॉल के वर्ग उदाहरण Typecast:
आईडी प्रतिनिधि = (आईडी) स्व; fbSession = [FBSession sessionForAplication: SHKFacebookKey getSessionProxy: SHKFacebookSessionProxyURL प्रतिनिधि: प्रतिनिधि];
आप # 2 चुनते हैं, तो यह बहुत की तरह, कक्षा तरीकों का उपयोग करने के लिए प्रोटोकॉल के उदाहरण तरीकों परिभाषित करने में मदद कर सकते हैं:
+ (void)protocolMethod { /* do stuff */ }
- (void)protocolMethod { [self.class protocolMethod]; }
कि भी आप अर्थ होगा उदाहरणों की जरूरत कभी नहीं। यह मदद करेगा क्योंकि अगर प्रोटोकॉल बदल जाएगा तो यह चेतावनियां जोड़ देगा। जब आप सम्मेलन का पालन करते हैं तो ये चेतावनियां वर्ग विधियों तक पहुंच जाएंगी।
शोर को कम करने के लिए, आप भी कुछ विधि बनाने एक स्थान पर समान किरदार को कम करने पर विचार हो सकता है:
+ (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return (id<SomeProtocol>)self;
}
- (id<SomeProtocol>)sharedSomeProtocolDelegate
{
return [[self class] sharedSomeProtocolDelegate];
}
तो आप लिख सकते हैं:
fbSession = [FBSession sessionForApplication:SHKFacebookKey
getSessionProxy:SHKFacebookSessionProxyURL
delegate:[self sharedSomeProtocolDelegate]];
(ध्यान दें कि के कार्यान्वयन इन प्रकार वास्तव में कक्षा क्लस्टर हैं, और आप डीबगर में कुछ अलग देखेंगे या मुद्रित किए गए हैं)
आपका संपादन स्पष्ट करता है। प्रोटोकॉल में केवल इंस्टेंस विधियां होती हैं और इनमें से कोई भी रिसीवर को संदर्भित नहीं करता है। मैं अभी भी स्पष्ट नहीं हूं, फिर, मुझे चेतावनी क्यों मिल रही है, अगर कोड आपके द्वारा वर्णित मानदंडों को पूरा करता है। – Jim
@Jim विवरण जोड़ा गया – justin