与独特和模糊的对象混淆

时间:2012-08-05 22:33:35

标签: objective-c nsnumber nscountedset

我认为NSCountedSet在频率上计算了numBnumC两次因为它们具有相同的值,所以我创建了两个Fraction个对象(未显示)类Fraction,我将ivarsnumeratordenominator)设置为彼此相等,但countForObject:将它们视为两个不同的对象并计算其频率各一个。 numAnumB指向内存中的不同位置但共享相同的值,并且两个Fraction对象指向内存中的不同位置但共享相同的值。为什么Number个对象被视为模糊不清,而不是Fraction个对象?

#import <Foundation/Foundation.h>
#import "Fraction.h"

int main (int argc, char *argv[]) {
    @autoreleasepool {
        NSNumber *numA = [NSNumber numberWithInt: 1];
        NSNumber *numB = [NSNumber numberWithInt: 2];
        NSNumber *numC = [NSNumber numberWithInt: 2];

        NSArray *array = [NSArray arrayWithObjects: numA, numB, numC, nil];

        NSCountedSet *mySet = [[NSCountedSet alloc] initWithArray: array];
        for (NSNumber *myNum in mySet) {
            NSLog(@"Number: %i Frequency: %lu", [myNum intValue], [mySet countForObject: myNum]);
        }

        }
    return 0;
}

2012-08-05 17:44:58.667 prog[1150:707] Number: 1 Frequency: 1
2012-08-05 17:44:58.669 prog[1150:707] Number: 2 Frequency: 2

1 个答案:

答案 0 :(得分:1)

为了让NSCountedSet和基金会的其余成员识别您的自定义类,您必须正确实施-isEqual:-hash。默认情况下,它们比较指针,因此即使两个对象表示相同的数据,它们也永远不会相等。对于-isEqual:类,Fraction的简单实现可能如下所示:

- (BOOL)isEqual: (id)anObject {
    #error Naive implementation. Do not use.
    if (anObject == self) {
        return YES;
    } else if ([anObject isKindOfClass: [Fraction class]]) {
        Fraction *reducedSelf = [self reducedFraction];
        Fraction *reducedOther = [anObject reducedFraction];
        if (reducedSelf.numerator == reducedOther.numerator && reducedSelf.denominator == reducedOther.denominator) {
            return YES;
        }
    }

    return NO;
}

- (NSUInteger)hash {
    #error Naive implementation. Do not use.
    Fraction *reducedSelf = [self reducedFraction];
    return reducedSelf.numerator ^ reducedSelf.denominator;
}

请注意,这不允许您将Fraction类的实例与NSNumber的实例进行比较。由于-isEqual: 必须是可交换的,并且因为相等的对象必须具有相同的哈希值,因此您需要提供与NSNumber兼容的实现(可能通过继承它并使用NSNumber的实现。)