2009-05-31 12 views
10

मेरे पास "नीति" ऑब्जेक्ट्स की एक श्रृंखला है जिसे मैंने पॉलिसी कक्षाओं के एक सेट पर कक्षा विधियों के रूप में लागू करने के लिए सुविधाजनक होगा। मैं इस के लिए एक प्रोटोकॉल निर्दिष्ट किया है, और (सिर्फ एक नीचे दिखाया गया है)कक्षा के संदर्भ के बिना मैं उद्देश्य सी में + कक्षा विधियों को कैसे कॉल करूं?

@protocol Counter 
+(NSInteger) countFor: (Model *)model; 
@end 

@interface CurrentListCounter : NSObject <Counter> 
+(NSInteger) countFor: (Model *)model; 
@end 

मैं तो कक्षाएं कि इस प्रोटोकॉल के अनुरूप (जैसे CurrentListCounter करता है) की एक सरणी है

+(NSArray *) availableCounters { 
return [[[NSArray alloc] initWithObjects: [CurrentListCounter class], [AllListsCounter class], nil] autorelease]; 
} 
के अनुरूप करने के लिए बनाया कक्षाएं

सूचना कैसे मैं वस्तुओं की तरह वर्गों का उपयोग कर रहा है (और यह मेरी समस्या हो सकती है - स्मालटाक कक्षाओं में सभी चीज़ों की तरह वस्तुओं रहे हैं - मुझे यकीन है कि अगर वे ऑब्जेक्टिव-सी में हैं नहीं कर रहा हूँ?)

मेरे सटीक समस्या है जब मैं पीओ में से एक लेता हूं तो मैं विधि को कॉल करना चाहता हूं सरणी से बाहर licy वस्तुओं:

id<Counter> counter = [[MyModel availableCounters] objectAtIndex: self.index]; 
return [counter countFor: self]; 

मैं वापसी कथन पर यह चेतावनी मिलती है - यह कहना है -countFor: प्रोटोकॉल में नहीं मिला (ताकि अपने अपने संभालने एक उदाहरण विधि जहां मैं एक वर्ग विधि कॉल करना चाहते हैं)। हालांकि, मेरी सरणी में ऑब्जेक्ट्स कक्षा के उदाहरण हैं, वे अब उदाहरण विधियों की तरह हैं (या अवधारणात्मक रूप से वे होना चाहिए)।

कक्षा विधियों को कॉल करने का कोई जादू तरीका है? या यह सिर्फ एक बुरा विचार है और मुझे सिर्फ अपनी नीति वस्तुओं के उदाहरण बनाना चाहिए (और वर्ग विधियों का उपयोग नहीं करना चाहिए)?

+0

काउंटर –

उत्तर

19

यह

id <Counter> counter = [[Model availableCounters] objectAtIndex:0]; 
return ([counter countFor: nil]); 

होना चाहिए

Class <Counter> counter = [[Model availableCounters] objectAtIndex:0]; 
return ([counter countFor: nil]); 

पहले में आप एक उदाहरण है कि <Counter> के अनुरूप है। दूसरे में आपके पास एक कक्षा है जो <Counter> के अनुरूप है। कंपाइलर चेतावनी सही है क्योंकि <Counter> के अनुरूप उदाहरण countFor: का जवाब नहीं देते हैं, केवल कक्षाएं ही होती हैं।

+0

मैं यह भी मानता हूं कि कक्षाओं की तुलना में उदाहरणों का उपयोग करना बेहतर लगता है। –

+0

यह उत्तर सही है - पहले मैंने कक्षा बनाम आईडी की उप-नोटिस नहीं देखी - जो वास्तव में मेरी पोस्ट के मूल शीर्षक का उत्तर देता है। – TimM

0

यह पता चला है कि यह वास्तव में काम कर रहा है और चेतावनी गलत है।

तो सवाल अभी भी खड़ा है कि क्या यह उचित बात है (कक्षा के तरीकों का उपयोग करें यदि उन्हें किसी राज्य की आवश्यकता नहीं है)?

और चेतावनी को सर्वोत्तम तरीके से कैसे संभालना है (मुझे चेतावनी मुक्त करना पसंद है)?

मेरी केवल वैकल्पिक हल एक दूसरे प्रोटोकॉल है (पहले के रूप में मूलतः एक ही है, लेकिन उदाहरण के पक्ष में यह घोषणा) के लिए किया गया था:

@protocol CounterInstance 
-(NSInteger) countFor: (Model *)model; 
@end 

और जहां मैं काउंटर का उपयोग करने के बजाय इसका इस्तेमाल (संकलक चाल करने के लिए):

id<CounterInstance> counter = [[MyModel availableCounters] objectAtIndex: self.index]; 
return [counter countFor: self]; 

यह थोड़ा अजीब है लेकिन काम करता है। दूसरों से विचारों में दिलचस्पी है?

+0

काउंटर काउंटर नहीं है चेतावनी गलत नहीं है। उद्देश्य-सी की गतिशील प्रकृति का अर्थ है कि संदेश वस्तु को किसी भी तरह भेजा जाता है। संकलक आपको यह बताने के लिए चेतावनी उठा रहा है कि यह वास्तव में एक उदाहरण विधि की उम्मीद कर रहा है। आपके समाधान के लिए - मुझे लगता है कि यह बदसूरत है। जिम ने जो किया वह बस करो। – Abizern

5

उद्देश्य-सी में एक वर्ग एक उदाहरण की तरह काम करता है - मुख्य अंतर्निहित अंतर यह है कि गिनती बनाए रखना उन पर कुछ भी नहीं करता है। हालांकि, आप जो उपलब्ध हैं, वह उपलब्ध है काउंटरर्स सरणी उदाहरण नहीं हैं (id प्रकार) लेकिन कक्षाएं, जिनमें Class का प्रकार है। इसलिए, -availableCounters परिभाषा के साथ आप ऊपर निर्दिष्ट, क्या आप की जरूरत यह है:

Class counterClass = [[MyModel availableCounters] objectAtIndex: self.index]; 
return ([counterClass countFor: self]); 

हालांकि, यह शायद शब्दार्थ बेहतर होगा कि आप कक्षाएं उदाहरणों के बजाय इस्तेमाल किया।के रूप में आप ऊपर निर्दिष्ट

static NSArray * globalCounterList = nil; 

+ (void) initialize 
{ 
    if (self != [Model class]) 
     return; 

    globalCounterList = [[NSArray alloc] initWithObjects: [[[CurrentListCounter alloc] init] autorelease], [[[SomeOtherCounter alloc] init] autorelease], nil]; 
} 

+ (NSArray *) availableCounters 
{ 
    return (globalCounterList); 
} 

फिर उस के आपके उपयोग वास्तव में होगा::

@protocol Counter 
- (NSUInteger) countFor: (Model *) model; 
@end 

@interface CurrentListCounter : NSObject<Counter> 
@end 

@interface SomeOtherCounter : NSObject<Counter> 
@end 

फिर अपने मॉडल वर्ग निम्नलिखित को लागू कर सकते हैं:

उस मामले में, आप की तरह निम्नलिखित कुछ कर सकते हैं
id<Counter> counter = [[Model availableCounters] objectAtIndex: self.index]; 
return ([counter countFor: self]); 
+0

धन्यवाद जिम - मुझे यह देखने में दिलचस्पी थी कि आप उद्देश्य-सी को कितनी दूर धक्का दे सकते हैं। ऐसा लगता है जैसे आप कक्षाओं को मारते हैं, जहां यह थोड़ा अलग तरीके से काम करना शुरू कर देता है (हालांकि यह काम करता है - कक्षाएं अभी भी वस्तुएं हैं, जो अच्छी है) - तो शायद यह उदाहरणों से चिपकने के लिए बेहतर हो सकता है। टिप्पणी की शुरुआत में एक चीज - "क्लास काउंटर क्लास" प्रोटोकॉल से परहेज कर रही है, जबकि मेरी कक्षाएं "काउंटर" के अनुरूप हैं। मुझे लगता है कि क्या गुम है कक्षाओं (कक्षा के किनारे) के लिए प्रोटोकॉल को सही ढंग से निर्दिष्ट करने में सक्षम है - कुछ: @interface CurrentListCounter: NSObject <+Counter> – TimM

+1

आप क्लास काउंटर क्लास का उपयोग करने में सक्षम हो सकते हैं। मुझे यकीन नहीं है। लेकिन ऐसा करने से केवल उन संदेशों को सीमित कर दिया जाता है जो संकलक चेतावनी नहीं देंगे - ओबीजेसी टाइप-चेकिंग वास्तव में केवल सलाहकार है। और प्रोटोकॉल कक्षा विधियों को निर्दिष्ट कर सकते हैं, इसलिए आपको किसी भी प्रकार की <+Counter> विशेष वाक्यविन्यास की आवश्यकता नहीं होगी (उदाहरण के लिए, NSObject प्रोटोकॉल को देखें)। –

+0

कूल - यह समाधान है: कक्षा काउंटर = [[मॉडल उपलब्ध काउंटर] .... यह संकलक को बताता है कि मेरे पास उस वर्ग का एक उदाहरण है जो उस प्रोटोकॉल के अनुरूप है। बेशक यह अभी भी स्वाद का सवाल है कि ऑब्जेक्ट्स के रूप में कक्षाओं का उपयोग ओब्जे-सी में है (आम सहमति नहीं है) – TimM

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