2012-02-20 4 views
7

एक दिलचस्प छोटी समस्या में भाग लें। जांच करने के लिए एक इकाई परीक्षणNSArray को NSSet में कनवर्ट करना, कस्टम क्लास इंस्टेंस ट्रांसफर असंगत रूप से

- (NSArray*)distinctObjectsByAddress { 
    NSSet* uniqueSet = [NSSet setWithArray:self]; 
    NSArray* retArray = [uniqueSet allObjects]; 

    return retArray; 
} 

और लिखा है:: मैं एक अनोखी विधि वस्तुओं के लिए एक सरणी फिल्टर करने के लिए लिख रहा था

- (void)testDistinctObjectsByAddress5 { 
    Person* adam1 = [[Person alloc] initWithFirstName:@"adam" lastName:@"adam" andParent:nil]; 
    Person* adam2 = [[Person alloc] initWithFirstName:@"adam" lastName:@"adam" andParent:nil]; 

    testPersonArray = [NSArray arrayWithObjects:adam1,adam2, nil]; 

    NSArray* checkArray = [testPersonArray distinctObjectsByAddress]; 

    STAssertEquals([checkArray count], [testPersonArray count], @"Array %@ counts should match %@ %@",checkArray,adam1,adam2); 
} 

सुंदर सरल। दिलचस्प हिस्सा यह है कि परीक्षण पास होने के लगभग 80-90% और हर बार यह विफल रहता है क्योंकि distinctObjectsByAddress विधि केवल एक वस्तु लौटाती है। मैं इसे [NSSet setWithArray:self] कॉल पर ढूंढने में सक्षम हूं लेकिन मैं यह भी सत्यापित करने में सक्षम हूं कि दो व्यक्ति वस्तुएं दो अलग-अलग वस्तुएं हैं (कम से कम उनके पास अलग पता है)। मुझे लगता है कि setWithArray: सिर्फ मूल पता तुलना कर रहा है लेकिन मुझे समझ में नहीं आता है कि कभी-कभी यह दो वस्तुओं का उत्पादन क्यों करता है जैसे कि इसे कभी-कभी केवल एक ही बनाना चाहिए।

कुछ मैंने अभी कोशिश की है adam2 बदल रहा था ताकि पहला और अंतिम नाम बिल्कुल adam1 जैसा ही न हो। यह त्रुटि को ठीक करने लगता है। क्या यह कुछ प्रकार के कंपाइलर ऑप्टिमाइज़ेशन को इंगित करता है जब ऑब्जेक्ट्स तार्किक रूप से समान होते हैं?

+4

मुझे लगता है कि समस्या व्यक्ति के साथ है और यह कैसे हैश और समानता विधियों को लागू करता है जो एनएसएसएटी उपयोग करता है। –

+1

यह 'isEqual:' का उपयोग करेगा जैसा कि वस्तुओं की तुलना करने के लिए 'NSObject' प्रोटोकॉल द्वारा परिभाषित किया गया है; क्या आपने इसे 'व्यक्ति' पर लागू किया है या 'हैश'? – Tommy

+1

हैश समस्या के अतिरिक्त, आप स्पष्ट रूप से nam के लिए adam1 और adam2 का परीक्षण नहीं कर रहे हैं। यदि कोई कभी-कभी इनिट करने में असफल रहता है, तो वह परीक्षण विफलता की व्याख्या करेगा। – bneely

उत्तर

9

मुझे लगता है कि setWithArray सिर्फ एक बुनियादी पता कर रही है यह सोचते हैं रहा हूँ

यह गलत है की तुलना करें। NSSet -isEqual: और -hash विधियों को उस ऑब्जेक्ट्स पर उपयोग करता है जो इसमें जोड़े गए हैं। यह इस बात पर निर्भर करता है कि उन्हें व्यक्ति या उसके सुपरक्लास में कैसे लागू किया जाता है।

यदि [person1 isEqual:person2] तो आप सेट को एक ऑब्जेक्ट रखने की अपेक्षा करेंगे। यदि नहीं, तो सेट में दो ऑब्जेक्ट्स होनी चाहिए।

मेरा अनुमान है कि व्यक्ति the rules का पालन नहीं करता है -isEqual: और -hash विधियों में। सबसे अधिक संभावना है कि, दो वस्तुएं बराबर हैं, लेकिन उनके हैंश समान नहीं हैं जैसे वे होना चाहिए। (समय है कि तुम भाग्यशाली हो रही है की 10-20% के अलावा।)

जब वस्तुओं तार्किक ही कर रहे हैं संकलक अनुकूलन के कुछ प्रकार के लिए इस बिंदु है?

नहीं, कोई कंपाइलर अनुकूलन नहीं है जो दो वस्तुओं को एक में विलय करेगा।

3

अधिकतर Person के लिए hash लागू नहीं किया गया था, और कभी-कभी समान Person ऑब्जेक्ट दो अलग-अलग बाल्टी में हैश करता है।

+0

हम्म, मैंने ओवरराइड किया है लेकिन कोई हैश नहीं है, इसलिए शायद यह समस्या है, इसलिए मैंने एनएसएससेट कोड को बाहर ले लिया है क्योंकि यह थोड़ा 'हैकी' लग रहा था और खुद को पतों की तुलना करने के लिए कोड लिखा था। लेकिन मुझे अभी भी वास्तव में दिलचस्पी है कि यह क्यों हो रहा था। यह हैश चीज शायद यह है, मैं जांच और स्वीकार करूँगा अगर यह है। – ACBurk

+0

डॉक्स प्रति @ACBurk "यदि दो ऑब्जेक्ट बराबर हैं, तो उनके पास एक ही हैश मान होना चाहिए।" (https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/NSObject।एचटीएमएल # // apple_ref/occ/intfm/NSObject/isEqual:); NSObject को सही ढंग से कार्यान्वित करने में विफलता किसी भी व्यवहार में वैध रूप से परिणाम दे सकती है। – Tommy

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