2010-03-01 8 views
5

यह एक शुरुआती सवाल है, इसलिए कृपया मेरे साथ भालू।क्या "कार्यान्वयन-केवल" वर्ग के सदस्य होना संभव है?

मुझे एक कक्षा मिली है जो किसी तृतीय-पक्ष लाइब्रेरी का उपयोग करती है (अगर यह मायने रखती है)। मैं लाइब्रेरी विधियों को पूरी तरह से सजाया जाना चाहता हूं, ताकि मैं कभी भी अपनी कक्षा के अंतर्निहित कार्यान्वयन को स्विच कर सकूं। कुछ की तरह:

// MyClass.h 

@interface MyClass : NSObject ... 

- (int) doSomething; 


// MyClass.m 

#import "some_library.h" 

@implementation MyClass 

- (int) doSomething 
{ 
    //call library's specific stuff 
} 

अब तक तो अच्छा, लेकिन अब मैं MyClass में एक उदाहरण चर कुछ पुस्तकालय से परिभाषित प्रकार (एक संरचना "some_library.h" में घोषित) है कि प्रयोग की आवश्यकता होती हूँ। बेशक मैं इंटरफ़ेस खंड में सही पुस्तकालय आयात कर सकते हैं:

//MyClass.h 

#import "some_library.h" 

@interface MyClass : NSObject { 
    some_library_t blah; 
} 
- (int) doSomething; 
@end 

लेकिन यह वास्तव में क्या मैं से बचने के लिए कोशिश कर रहा हूँ है - MyClass इसके कार्यान्वयन के विवरण के बारे में पता के उपयोगकर्ताओं बनाते हैं।

क्या मैं किसी भी तरह से अपने वर्ग 'इंटरफ़ेस से लाइब्रेरी-विशिष्ट प्रकारों को "छुपा" सकता हूं? मानक अभ्यास क्या है?

उत्तर

8

मानक अभ्यास या तो पुस्तकालय प्रकार या एक कस्टम कार्यान्वयन संरचना (- कार्यान्वयन सूचक इस तरह अपनी भी Pimpl कहा जाता है) के लिए opaque pointers उपयोग करने के लिए है।

ऐसा करने के लिए आपको यह जानना होगा कि आप पॉइंटर्स को अपूर्ण प्रकारों को परिभाषित कर सकते हैं, यानी टाइप जिन्हें आप केवल अस्तित्व में घोषित करते हैं। उदा .:

struct FooImpl; 

@interface Foo { 
    struct FooImpl* impl; // using pointer is ok for incomplete types 
}   
@end 

फिर आप कार्यान्वयन फ़ाइल में प्रकार को परिभाषित कर सकते हैं:

struct FooImpl { 
    // ... member definition 
}; 

और आवंटित/यह उदाहरण के लिए प्रारंभ आपके -(id)init विधि में।

FooImpl लाइब्रेरी प्रकार एक संरचना थी, तो आप SomeLibraryType भी हो सकते हैं - फिर आप इसे उसी तरह घोषित करेंगे और स्रोत फ़ाइल में लाइब्रेरी हेडर शामिल करेंगे, जो आपको structs परिभाषा देता है।

+0

मेरे बुरा, तय की। मैं 'संरचना' उपयोग के लिए सी ++ सुविधा के लिए भी उपयोग किया गया है। –

3

जीएफ का उत्तर मर चुका है, लेकिन एक और तरीका भी है। एक अपारदर्शी वर्ग का प्रयोग करें।

Foo.h:

@interface Foo : NSObject 
{ 
    id internalGunk; 
} 
@end 

Foo.m:

#import "Foo.h" 

@interface PrivateStuff:NSObject 
... declare ivars and/or properties and/or methods here ... 
@end 

@implementation PrivateStuff 
... any custom implementation and/or @synthesizes here ... 
@end 

#define SELF_PRIVVY ((PrivateStuff *)internalGunk) 
@implementation Foo 
... implementation here ... 
@end 

आप SELF_PRIVVY पसंद नहीं है, तो आप कुछ इस तरह कर सकते हैं:

// in Foo's @implementation 
- (PrivateStuff *) privateStuff { return internalGunk; } 

उपरोक्त पैटर्न (इसमें से सभी) के कुछ फायदे हैं। सबसे पहले, यह जीसी के साथ पूरी तरह से संगत है कि सब कुछ वस्तु संदर्भ के रूप में घोषित किया जाता है। दूसरा, यदि आवश्यक हो तो निजी सामान को एक अलग वर्ग में पुन: सक्रिय करना बहुत आसान है। अंत में, निजीकृत रखने के लिए उस वर्ग को रखने से, उस निजी सामान से संबंधित किसी भी तर्क या दृढ़ता को अन्य सभी चीज़ों से अलग करना आसान हो जाता है; यह भविष्य में रिफैक्टरिंग को आसान बना देगा।

चाहे आपकी आवश्यकताओं के लिए यह बेहतर समाधान है या नहीं, आपकी विशिष्ट आवश्यकताओं पर निर्भर करता है।

0

मैंने पढ़ा है कि LLVM 3.0 के बाद से, आप अंतरफलक के कर्ली कोष्ठक अनुभाग स्थानांतरित कर सकते हैं (एक ivars घोषित) कार्यान्वयन के लिए (मीटर फ़ाइल, @implementation ब्लॉक के अंदर)

स्रोत: http://www.raywenderlich.com/5773/beginning-arc-in-ios-5-tutorial-part-2

(लिंक एक एआरसी ट्यूटोरियल है, लेकिन यह नई सुविधा एआरसी से स्वतंत्र है)।

व्यक्तिगत रूप से, मैं दोनों आश्चर्यचकित और खुश हूं।

संपादित करें: ऐसा लगता है यह Xcode 4.2 के बाद से है:

What's the difference between adding pseudo-private ivars in a class extension or in the @implementation block?

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