2011-12-01 20 views
7

बस सोच रहा है:क्यों [NSMutableString stringWithString: @ ""] काम करता है?

NSString में +stringWithString: नामक एक स्थिर विधि है। NSMutableString में इसे पुनः लोड/ओवरराइड नहीं किया गया है, इसलिए हम यह नहीं मान सकते कि यह NSMutableString लौटाएगा। वास्तव में भी NSString वर्ग में वापसी प्रकार और id के रूप में परिभाषित किया गया है doc states:

वापसी मूल्य
aString से पात्रों को कॉपी करके बनाया एक स्ट्रिंग।

मेरे ज्ञान में उद्देश्य सी का क्या हिस्सा है, यह समझने के लिए कि यह क्यों काम करता है और NSMutableString देता है? विशेष रूप से क्योंकि बेस क्लास NSString इस बात से अवगत नहीं है कि हम बदले में एक परिवर्तनीय स्ट्रिंग चाहते हैं।

एक कह सकते हैं आंतरिक [Class alloc] कहा जाता है कि किस प्रकार NSMutableString की एक वस्तु उत्पन्न होगा, लेकिन जैसा कि हम स्रोत कोड की जरूरत नहीं है और stringWithString: कर सकता है जो कुछ भी वह आंतरिक रूप से चाहता है यहां तक ​​कि इस शुद्ध अटकलबाजी है।

क्या उन सभी वर्ग विधियों को उप-वर्ग में पुन: कार्यान्वित किया गया है? और यदि हां यह दस्तावेज क्यों नहीं है?

उत्तर

6

एनएसएसटींग में + स्ट्रिंगविथस्ट्रिंग नामक एक स्थिर विधि है:।

अधिक स्वीकार्य रूप से, यह एक क्लास विधि है।

यह redeclared नहीं है/NSMutableString

कोको में अधिरोहित, उपवर्ग redeclare विधि की जरूरत नहीं है। वास्तव में, यह सिर्फ बहुत शोर (आईएमओ) का उत्पादन करेगा। इसे केवल को को अपने कस्टम कार्यान्वयन प्रदान करने की विधि को फिर से परिभाषित करने की आवश्यकता है।

इसलिए हम यह नहीं मान सकते कि यह एक एनएसएमयूटेबलस्ट्रिंग वापस कर देगा।

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

मेरे ज्ञान में उद्देश्य सी का क्या हिस्सा है, यह समझने के लिए कि यह क्यों काम करता है और एनएसएमयूटेबल स्ट्रिंग देता है? विशेष रूप से क्योंकि बेस क्लास एनएसएसटींग को पता नहीं है कि हम बदले में एक परिवर्तनीय स्ट्रिंग चाहते हैं।

यह 'जानता है' क्योंकि आपने [NSString stringWithString:@"bah"] के बजाय लिखा है। उदाहरण के तरीकों की तरह, कक्षा विधियों में एक अंतर्निहित self है जो उन्हें कक्षा विधियों के माध्यम से प्रकार को पारित करने की अनुमति देता है। इसलिए, आवश्यकतानुसार वर्ग विधियों को फिर से परिभाषित/ओवरराइड किया जा सकता है। वर्ग विधियां self का उपयोग अपने प्रकार को निर्धारित करने या संदेश भेजने के लिए भी कर सकती हैं (उदाहरण शीघ्र ही)।

एक कह सकते हैं आंतरिक रूप से [क्लास alloc] कहा जाता है कि किस प्रकार NSMutableString की एक वस्तु उत्पन्न होगा, लेकिन फिर भी यह शुद्ध अटकलबाजी के रूप में हम स्रोत कोड की जरूरत नहीं है और stringWithString है कि: जो कुछ भी कर सकता है वह आंतरिक रूप से चाहता है।

यह अनुमान नहीं होना चाहिए। इस मामले में, यदि आपको अपरिवर्तनीय स्ट्रिंग लौटा दी गई है, तो आपको एक बग फाइल करना चाहिए। अन्यथा, यह विज्ञापित के रूप में काम करता है, भले ही उन्होंने एक या अधिक परिभाषाओं का उपयोग किया हो।

क्या उन सभी वर्ग विधियों को उप-वर्ग में पुन: कार्यान्वित किया गया है?

इस प्रकार का कार्यान्वयन रूप ले सकता है::

@implementation NSString 
+ (id)stringWithString:(NSString *)arg 
{ 
    // self is either +NSString or +NSMutableString 
    return [[[self alloc] initWithString:arg] autorelease]; 
} 

हालांकि अपवाद अक्सर बनाया जा सकता है

सुविधा कंस्ट्रक्टर्स के मामले में, यह नामित initializers में से एक के माध्यम से जाना और अधिक आम है , और अक्सर अनुकूलित अपरिवर्तनीय/परिवर्तनीय प्रकारों के मामले में होता है:

@implementation NSString 
+ (id)stringWithString:(NSString *)arg 
{ 
    return [arg imp_isMutable] ? [[[self alloc] initWithString:arg] autorelease] : arg; 
} 
... 
@implementation NSMutableString 
+ (id)stringWithString:(NSString *)arg 
{ 
    return [[[self alloc] initWithString:arg] autorelease]; 
} 
... 

और यदि हां यह दस्तावेज क्यों नहीं है?

वे redeclared नहीं किया जाना चाहिए या redocumented जब फर्क सिर्फ इतना वर्ग प्रकार है जो आप का अनुरोध किया है, जब तक वे आधार वर्ग या विशेष टिप्पणी से कुछ विचलन है - यहां तक ​​कि उस मामले में, यह बेहतर होगा एक और नाम के साथ एक विधि बनाएँ।

+0

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

+1

@ जोरीस काफी नहीं; क्लास विधियों को सामान्य पैटर्न के साथ कार्यान्वित किया जाता है, तो उप वर्ग को किसी भी वर्ग विधियों को ओवरराइड करने की आवश्यकता नहीं है। अर्थात। यदि '+ stringWithString:' को 'वापसी [[[self alloc] initWithString: ...] autorelease] के रूप में कार्यान्वित किया गया है; तो उस विधि को ओवरराइड करने के लिए NSMutableString की आवश्यकता नहीं है (हालांकि इसे' -initWithString को ओवरराइड करने की आवश्यकता होगी : इसके बजाए 'इंस्टेंस विधि)। – bbum

+0

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

3

NSMutableStringNSString का उप-वर्ग है, इस प्रकार NSMutableString पर बुलाया जाने वाला कोई भी तरीका उचित तरीके से काम करने की उम्मीद की जा सकती है, और NSMutableString को समझ में आने पर उसे वापस कर सकते हैं। दिमाग में आने वाली एकमात्र विधि जो कि इसका पालन नहीं करती है, हालांकि copy है जो सम्मेलन द्वारा एक अपरिवर्तनीय उदाहरण देता है।

यही कारण है कि अपने प्रारंभकर्ता तरीकों एक ठोस उदाहरण के बजाय id लौटने के लिए, और क्यों सभी वर्ग के तरीकों [self alloc] बजाय [MYActualClass alloc] उपयोग करना चाहिए। अब

+ (id) stringWithString: (NSString*) foo 
{ 
    return [[self alloc] initWithString:foo]; 
} 

जब आप NSString पर इस प्रारंभकर्ता फोन, [self alloc] रिटर्न NSString और आप NSString वापस का एक उदाहरण मिलता है:

3

आप इस तरह एक सा प्रारंभकर्ता लिख ​​सकते हैं। लेकिन जब आप [NSMutableString stringWithString:@"…"] पर कॉल करते हैं, तो [self alloc] संदेश का परिणाम NSMutableString है, और इसलिए प्रारंभकर्ता एक परिवर्तनीय स्ट्रिंग देता है।

+0

यह संभवतः एक स्मृति रिसाव का उत्पादन करेगा। विधि का नाम 'स्ट्रिंगविथस्ट्रिंग:' [तात्पर्य] (https://developer.apple.com/library/mac/#documentation/General/Conceptual/DevPedia-CocoaCore/MemoryManagement.html#//apple_ref/doc/uid/TP40008195- सीएच 27-एसडब्ल्यू 3) कि लौटे ऑब्जेक्ट का स्वामित्व रिसीवर को स्थानांतरित नहीं किया जाता है। –

+0

मुझे लगता है कि यह एआरसी से पहले लिखा गया था, इसलिए यह वास्तव में एक रिसाव था, लेकिन आज एआरसी के साथ यह उम्मीद के अनुसार काम करता है। – zoul

+0

आपको अभी भी अच्छी मेमोरी प्रबंधन का अभ्यास करना चाहिए ... –

3

(क्या जस्टिन ने कहा, लेकिन एक स्पष्टीकरण)

NSString में एक स्थिर विधि + stringWithString कहा जाता है :. यह एनएसएमयूटेबलस्ट्रिंग में पुनः लोड/ओवरराइड नहीं किया गया है, इसलिए हम नहीं मान सकते हैं कि यह एक NSMutableString वापस करेगा।यहां तक ​​कि NSString कक्षा में वास्तव में वापसी प्रकार आईडी के रूप में परिभाषित किया गया है ...

सबसे पहले, ऑब्जेक्टिव-सी स्थिर तरीकों जरूरत नहीं है। उद्देश्य-सी में वर्ग विधियां है। कक्षा के तरीके बिल्कुल उदाहरण विधियों (जहां वर्ग मेटाक्लास का उदाहरण है) का व्यवहार करता है और विरासत में प्राप्त, ओवरराइड किया जा सकता है ...

इस प्रकार, NSMutableStringcharacterAtIndex: विरासत में है और कुछ विशेष करने के लिए इसे ओवरराइड कर सकता है, आवश्यक, NSMutableString कक्षा विधियों के लिए भी ऐसा ही कर सकता है।

यह भी ध्यान दें कि शीर्षलेख में एक विधि घोषित करने के लिए कक्षा की आवश्यकता नहीं है जो इसे अपने सुपरक्लास से ओवरराइड करता है। ढांचे में वर्ग आमतौर पर स्पष्ट रूप से ओवरराइड विधियों की घोषणा नहीं करते हैं क्योंकि ओवरराइड विधि को माता-पिता के रूप में बिल्कुल व्यवहार करना चाहिए, लेकिन उप-वर्ग की आवश्यकताओं के संदर्भ में काम करने के लिए ओवरराइड किया गया है।

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