2011-05-05 15 views
15

मैकोज़-एक्स 10.6.7 और एक्सकोड 4.0.2 पर ऑब्जेक्टिव-सी में प्रतिक्रिया-टोसे चयनकर्ता विधि के साथ खेल रहा था, यह पहचानने के लिए कि कोई ऑब्जेक्ट कुछ संदेशों का जवाब देगा या नहीं। मैनुअल के मुताबिक, एनएसएसटींग को एपेंडस्ट्रिंग का जवाब नहीं देना चाहिए: जबकि एनएसएमयूटेबलस्ट्रिंग को चाहिए। यहाँ कोड का टुकड़ा है जो यह परीक्षण है:एनएसएसटींग ने एपेंडस्ट्रिंग का जवाब क्यों दिया?

int main (int argc, const char * argv[]) 
{ 

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSString *myString = [[NSString alloc] init]; 

    if ([myString respondsToSelector:@selector(appendString:)]) { 
     NSLog(@"myString responds to appendString:"); 
    } else { 
     NSLog(@"myString doesn't respond to appendString:"); 
    } 

    // do stuff with myString 

    [myString release]; 
    [pool drain]; 
    return 0; 
} 

और यहां उत्पादन है:

Class02[10241:903] myString responds to appendString: 

मैं इन सबसे छुटकारा विपरीत उम्मीद था। एनएसएसटींग ऑब्जेक्ट एपेंडस्ट्रिंग का जवाब कैसे देता है:? यहाँ क्या हो रहा है कि मैं याद कर रहा हूँ?

+0

यदि आपने इसे वास्तविक 'appendString भेजा है:' संदेश कुछ भी उड़ाता है? – BoltClock

+1

हां: 'अपेंडस्ट्रिंग के साथ अपरिवर्तनीय ऑब्जेक्ट को म्यूट करने का प्रयास:'। – zoul

+0

@ बोल्टक्लॉक: हां यह उड़ाता है, लेकिन यह नहीं है कि 'प्रतिक्रियाओं का चयन करने का बिंदु' चयनकर्ता, 'विधि, इसे जांचने के लिए इसे वास्तविक' appendString: 'संदेश भेजने से पहले उड़ा नहीं होगा? – user698769

उत्तर

1

आपको पर एक विधि के बारे में धारणा नहीं करनी चाहिए। उस विधि का आंतरिक रूप से उपयोग किया जा सकता है या किसी भी कारण से यह अस्तित्व में है। तकनीकी रूप से, यह सिर्फ निजी एपीआई है।

आपके पास केवल सार्वजनिक घोषणाओं (दस्तावेज़) का अनुबंध है, और वे वह संदेश नहीं दिखाते हैं। तो यदि आप अन्य सुविधाओं का उपयोग करते हैं तो परेशानी में आने के लिए तैयार रहें।

+0

सहमत हुए, लेकिन कोई तर्क दे सकता है कि अपवाद फेंकने के लिए केवल एक विधि का समर्थन करना अजीब है। यह बतख टाइपिंग के खिलाफ चला जाता है - यह विशेष बात एक बतख की तरह चलता है, लेकिन वास्तव में एक बतख नहीं है। – zoul

+0

@zoul: मैंने देखा है कि 'NotImplementedException को अन्य भाषाओं में जगह पर फेंक दिया गया है। अगर कुछ ऐसा ही हुआ तो मुझे आश्चर्य नहीं होगा। लेकिन आपका जवाब अधिक समझदार लगता है। – BoltClock

2

शायद इसे कार्यान्वयन के साथ करना है। NSString एक वर्ग क्लस्टर है, जिसका अर्थ है कि NSString सिर्फ एक सार्वजनिक इंटरफ़ेस है और वास्तविक कार्यान्वयन वर्ग अलग है (see what the class message gives you)।

और एक ही समय NSString पर भी टोल फ्री CFString को पाट है, जिसका अर्थ है कि आप स्वतंत्र रूप से सिर्फ कास्टिंग द्वारा उन दो प्रकार से पहले स्विच कर सकते हैं:

NSString *one = @"foo"; 
CFStringRef two = (CFStringRef)one; // valid cast 

जब आप एक नया स्ट्रिंग बनाने तुम सच में एक मिल NSCFString वापस, CFString के आसपास एक पतली आवरण। और मुद्दा यह है कि जब आप एक नई म्यूटेबल स्ट्रिंग बनाते हैं, तो आपको NSCFString का उदाहरण भी मिलता है।

Class one = [[NSString string] class]; // NSCFString 
Class two = [[NSMutableString string] class]; // NSCFString 

मैं इस दृश्य के कार्यान्वयन बिंदु से सुविधाजनक लगता था - दोनों NSString और NSMutableString एक आम वर्ग (= कम कोड दोहराव) और इस वर्ग का समर्थन हासिल किया जा सकता है सुनिश्चित करें कि आप अचल स्थिति का उल्लंघन नहीं करते बनाता है:

// “Attempt to mutate immutable object with appendString:” 
[[NSString string] appendString:@"foo"]; 

इस उत्तर में बहुत सारे अनुमान हैं और मैं वास्तव में सामान को समझ नहीं पा रहा हूं, आइए आशा करते हैं कि कोई बेहतर जानता है।

10

संक्षिप्त उत्तर: वह स्ट्रिंग NSCFString है, जो NSMutableString से प्राप्त एक वर्ग है, इसलिए यह सुपरक्लास सहित NSMutableString में घोषित विधियों के लिए चयनकर्ताओं का जवाब देती है।

इतना छोटा जवाब नहीं: फाउंडेशन स्ट्रिंग कोर फाउंडेशन तारों के साथ टोल-फ्री हैं। डेवलपर्स इन स्ट्रिंग्स को संदर्भित करने के लिए अपारदर्शी प्रकार CFStringRef (NSString के साथ ब्रिज किए गए) और CFMutableStringRef (NSMutableString के साथ ब्रिज किया गया), पहली नज़र में, दो अलग-अलग प्रकार के तार होते हैं: अपरिवर्तनीय और परिवर्तनीय।

एक कोर फाउंडेशन आंतरिक कार्यान्वयन दृष्टिकोण से, वहाँ एक निजी प्रकार struct __CFString कहा जाता है। यह निजी प्रकार एक छोटा सा क्षेत्र रखता है जो अन्य जानकारी के साथ स्टोर करता है, चाहे स्ट्रिंग उत्परिवर्तनीय या अपरिवर्तनीय हो।एक प्रकार का होना कार्यान्वयन को सरल बनाता है क्योंकि कई कार्यों को अपरिवर्तनीय और परिवर्तनीय तारों द्वारा साझा किया जाता है।

जब भी एक कोर फाउंडेशन फ़ंक्शन जो उत्परिवर्तनीय तारों पर चल रहा है उसे कॉल किया जाता है, तो यह पहले उस बिट फ़ील्ड को पढ़ता है और जांचता है कि स्ट्रिंग उत्परिवर्तनीय या अपरिवर्तनीय है या नहीं। यदि तर्क एक परिवर्तनीय स्ट्रिंग माना जाता है लेकिन वास्तव में यह नहीं है, तो फ़ंक्शन एक त्रुटि देता है (उदा। _CFStringErrNotMutable) या कोई दावा विफल रहता है (उदा। __CFAssertIsStringAndMutable(cf))।

किसी भी दर पर, ये कार्यान्वयन विवरण हैं, और वे भविष्य में बदल सकते हैं। तथ्य यह है कि NSString-appendString: घोषित नहीं करता है इसका मतलब यह नहीं है कि प्रत्येक NSString उदाहरण संबंधित चयनकर्ता का जवाब नहीं देता है - substitutability सोचें। एक ही स्थिति अन्य परिवर्तनीय/अपरिवर्तनीय कक्षाओं जैसे NSArray और NSMutableArray पर लागू होती है। डेवलपर परिप्रेक्ष्य से, महत्वपूर्ण बात यह है कि लौटाई गई वस्तु एक प्रकार का है जो रिटर्न प्रकार से मेल खाती है - यह प्रकार या स्वयं के उस प्रकार का उप प्रकार हो सकता है। कक्षा क्लस्टर इसे एक और अधिक गड़बड़ कर देते हैं लेकिन स्थिति प्रति वर्ग क्लस्टर तक ही सीमित नहीं है।

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


आप CFShowStr() फ़ंक्शन का उपयोग एक स्ट्रिंग से जानकारी प्राप्त कर सकते हैं। अपने प्रश्न में उदाहरण में, जोड़ने

CFShowStr((CFStringRef)myString); 

आप एक निर्गम के लिए इसी तरह मिलना चाहिए:

Length 0 
IsEightBit 1 
HasLengthByte 0 
HasNullByte 1 
InlineContents 0 
Allocator SystemDefault 
Mutable 0 
Contents 0x0 

जहां

Mutable 0 

मतलब यह है कि स्ट्रिंग तथ्य अपरिवर्तनीय है।

+0

यही वह जवाब है जिसके लिए मैं उम्मीद कर रहा था, धन्यवाद! – zoul

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