2013-06-17 6 views
6

मैं एक ढांचा वर्ग से उत्तराधिकारी होना चाहता हूं जिसमें फैक्ट्री विधि है। मैं फैक्ट्री विधि को अपने विरासत वर्ग प्रकार की वस्तु कैसे वापस कर सकता हूं? मुझे this useful article मिला जो एक समान स्थिति का वर्णन करता है लेकिन उनके मामले में आपके पास सुपरक्लास पर नियंत्रण होता है। मैं UIImage का उप-वर्ग कैसे लिख सकता हूं, imageNamed: मेरे सबक्लास प्रकार का ऑब्जेक्ट लौटाएगा?फैक्टरी विधियों के साथ उद्देश्य सी वर्ग विरासत

+2

शायद आप UIImage पर एक श्रेणी लिखकर जो चाहते हैं उसे प्राप्त कर सकते हैं? –

+0

हां, अब मैं इस दिशा के बारे में सोच रहा हूं। केवल मुझे कुछ अतिरिक्त वर्ग के सदस्यों (गुणों) की आवश्यकता है और objc_setAssociatedObject और दोस्तों के साथ परेशानी से बचना चाहता था। इसके अलावा क्योंकि मुझे पूरी तरह से अलग समस्या के लिए इस प्रकार के कामकाज को बनाने के लिए यह सुरुचिपूर्ण नहीं लगता है। हालांकि मुझे और अधिक डर है कि मेरे पास कोई विकल्प नहीं है। – MrTJ

+1

इस [NSObject] (https://github.com/pixelflut/PixLib-OpenSource/blob/master/PixLib%20OpenSource/NSObject%2BPixLib.m) श्रेणी पर एक नज़र डालें। दो विधियों 'setRuntimeProperty: नाम:' और 'रनटाइमप्रोपर्टी:' विश्वसनीय वस्तुओं को सेट करने और संबंधित वस्तुओं तक पहुंचने में सहायता करें। –

उत्तर

9

मैं एक फ्रेमवर्क क्लास से उत्तराधिकारी होना चाहता हूं जिसमें फैक्ट्री विधि है। मैं फैक्ट्री विधि को अपने विरासत वर्ग प्रकार की वस्तु कैसे वापस कर सकता हूं?

@interface MONImage : UIImage 
@end 

@implementation MONImage 
@end 

तब:

यह सब आप क्या करना है चाहिए

MONImage * image = [MONImage imageNamed:name]; 

मैं कैसे लिख सकता है, कहते हैं, UIImage का एक उपवर्ग कि imageNamed: मेरे उपclass प्रकार का एक वस्तु वापस कर देगा?

+[UIImage imageNamed:] के कार्यान्वयन ने इस दृष्टिकोण से उप-वर्गों को लिखा। नतीजतन, आपको इस विधि को स्वयं लागू करने की आवश्यकता होगी।

यहाँ कैसे एक घोषित करना चाहिए एक कारखाने विधि है:

+ (instancetype)imageNamed:(NSString *)pName; 

और कैसे एक इसे लागू करना चाहिए:

+ (instancetype)imageNamed:(NSString *)pName 
{ 
    MONImage * image = [[self alloc] initWithThisDesignatedInitializer:pName]; 
         ^^^^ NOTE: self, not a concrete class 
    ...set up image... 
    return image; 
} 

पर वे इसे उस तरह से नहीं किया - +[UIImage imageNamed:] लिखा था जब आप MONImage * img = [MONImage imageNamed:pName]; लिखते हैं तो उप-वर्ग बाहर निकलते हैं और UIImage लौटाते हैं। कभी-कभी यह एक अच्छे कारण के लिए किया जाता है। कुछ तरीकों में 'अंतिम' अर्थशास्त्र होना चाहिए। यह तब दिखाई देता है जब आपकी विधि क्लास क्लस्टर में कई प्रकार की वापसी कर सकती है। भाषा 'अंतिम' विधियों को व्यक्त नहीं करती है - लेकिन ऐसी विधि को कम से कम दस्तावेज किया जाना चाहिए।


तो यह UIImage मामले के लिए चारों ओर आने के लिए:

@interface MONImage : UIImage 

+ (instancetype)imageNamed:(NSString *)pName; 

@end 

@implementation MONImage 

+ (instancetype)imageNamed:(NSString *)pName 
{ 
    UIImage * source = [UIImage imageNamed:pName]; 
    CGImageRef cgImage = source.CGImage; 
    if (cgImage) 
     return [[self alloc] initWithCGImage:cgImage]; 
    // try it another way 
    return nil; 
} 

@end 

ध्यान दें कि UIImage और CGImage रों अपरिवर्तनीय हैं। इसके परिणामस्वरूप छवि डेटा की गहरी प्रति नतीजा नहीं होनी चाहिए।

+2

+1। – Abizern

+2

क्या यह '[UIImage imageNamed:]' के कैशिंग व्यवहार भी प्रदान करता है? यदि नहीं, तो शायद आपको 'MONImage' में मूल छवि का संदर्भ संग्रहीत करना चाहिए। लेकिन वास्तव में अच्छा समाधान है। –

+0

@ जोनाथन सिचॉन यह '+ छवि नामित: 'के लुकअप व्यवहार को संरक्षित रखेगा। यह छवि लोड करेगा, फिर इसे कैश करेगा। कैशिंग कार्यान्वयन का सटीक व्यवहार सारणित है इसलिए मेरा निष्कर्ष यह है कि इस संबंध में समान होने की गारंटी नहीं है। मुझे लगता है * कैशिंग के संबंध में यह वही होगा, लेकिन मैंने यह साबित नहीं किया है। अच्छा प्रश्न। – justin

2

अपने उदाहरण के लिए:

  • उपवर्ग के लिए, कहते हैं UIImage, MyImage
  • कुछ भी विशिष्ट आप के लिए किया जाना चाहिए कि ऐसा करने के लिए imageNamed: विधि को लागू करें।
  • कॉल उस वर्ग पर कि विधि: MyImage *newImage = [MyImage imageNamed:imageName];
+2

यह वास्तव में मदद नहीं करेगा, क्योंकि आप 'imageNamed' के अपने कार्यान्वयन में 'सुपर' नहीं कह सकते हैं, क्योंकि यह 'UIImage' प्रकार के उदाहरण को वापस करने में समाप्त होगा। –

+0

कौन कहता है कि उसे सुपर कॉल करने की आवश्यकता है? वह विधि के भीतर अपने उपclass के एक वस्तु को आवंटित और init कर सकते हैं और उसे वापस कर सकते हैं। और, जैसा कि हम सभी जानते हैं, सम्मेलन उपclasses के लिए अपने सुपरक्लास के नामित प्रारंभिक कॉलर को कॉल करने के लिए है, जो 'id' प्रकार का ऑब्जेक्ट देता है। वैसे भी, ओपी के बारे में पूछे जाने पर आधारित यह एक संक्षिप्त उदाहरण है। विवरण उपयोगकर्ता को छोड़ दिया गया है, लेकिन एक सुविधा कन्स्ट्रक्टर आवंटन का सिद्धांत और इसकी अपनी कक्षा के किसी ऑब्जेक्ट को init'ing ध्वनि है। – Abizern

+1

हां, लेकिन इस मामले में, 'जादू' सेब 'छवि में किया गया है नामित:' बहुत उपयोगी है और मुझे नहीं लगता कि वह इसे स्वयं लागू करना चाहता है। लेकिन आप सही हैं, आपका जवाब 'गलत' नहीं है, लेकिन मुझे लगता है कि इस मामले में बहुत उपयोगी नहीं है। –

0

दृष्टिकोण है कि मेरी समस्या हल (क्रेडिट मेरे सवाल की टिप्पणियों में जोनाथन Cichon करने के लिए जाना) विरासत के बजाय एक वर्ग का इस्तेमाल किया गया। मैंने श्रेणी कार्यान्वयन में अतिरिक्त डेटा घोषित करने और स्टोर करने के लिए Associative References का उपयोग किया क्योंकि एसओ में बहुत कुछ चर्चा की गई। मैं जोनाथन द्वारा प्रस्तावित NSObject category implementation पर ध्यान देना चाहता हूं जो किसी ऑब्जेक्ट को सहयोगी संदर्भ जोड़ने के लिए वास्तव में आसान और सुरुचिपूर्ण बनाता है।

+0

जबकि मुझे खुशी है कि आपने अपनी समस्या हल की है - आपका प्रश्न सुविधा निर्माणकर्ताओं को ओवरराइड करने के बारे में था, जिसे आपने कक्षा विस्तार के बाहर कक्षा में संग्रहण जोड़ने के बारे में एक प्रश्न में बदल दिया। तो वास्तव में एक ही समय में प्रश्नों और उत्तरों के दो सेट चल रहे हैं। – Abizern

+0

मुझे अतिरिक्त डेटा के साथ मूल रूपरेखा वर्ग का विस्तार करने की आवश्यकता है और फिर भी इसकी मूल सुविधा रचनाकारों का उपयोग करने में सक्षम होना चाहिए। जब मैंने मूल प्रश्न पूछा तो मुझे नहीं पता था कि यह कैसे करें और माना जाता है कि इसे विरासत के साथ हासिल किया जा सकता है। आप इस दृष्टिकोण से सही हैं कि मैंने बिल्कुल निर्दिष्ट नहीं किया है कि मुझे कक्षा में अतिरिक्त डेटा जोड़ने की आवश्यकता है, लेकिन "विरासत" लिखा है। दूसरी ओर जोनाथन का समाधान पूरी तरह से मेरी समस्या हल करता है भले ही विरासत का उपयोग न करें। – MrTJ

+0

एनबी: मैंने मूल प्रश्न नहीं बदला और भविष्य में पाठकों के संदर्भ के रूप में केवल इस जवाब में assoc.refs का संकेत जोड़ा। – MrTJ

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