2009-05-18 104 views
23

如何比较自定义类的两个对象?我的想法是向类中添加一个额外的方法,在该方法中,我可以将当​​前对象与另一个同类对象进行比较。如何比较Objective-C中的对象?

所以我可以写我自己的代码,如何比较每个类的字段。

这就是我该怎么做的。还是有一些预定义的方法来做到这一点?就像NSString类的“isEqualTo”一样?

回答

53

-isEqual:指针是好的,但如果你实现-isEqual:,你绝对必须也以这样一种方式,如果两个物体的-isEqual:返回YES他们也将返回相同的值-hash实施-hash。实施isEqual:而不实施-hash导致一些非常令人惊讶的错误,当你使用集合像NSArray。

对于新的开发者,我倾向于建议不要超载-isEqual:。我建议改为使用与NSString相同的技术,并创建一个自定义-isEqualToFoo:(其中Foo是您的课程),直到您了解-isEqual:对集合的影响并特别需要此行为。重载-isEqual:强大,但你可以创建的错误是微妙的。在许多情况下创建您自己的自定义比较器更安全,更清晰。

+0

Hi Rob。很好的答案!由于我是“新开发人员”,因此我会按照您的建议完成。这就是我首先想到的。非常感谢。 – TalkingCode 2009-05-18 14:23:09

6

标准方法是覆盖- (BOOL)isEqual:(id)anObject- (NSUInteger)hash

您应该阅读NSObject protocolthis的文档SO问题有关如何编写散列方法的一些有趣的答案。

1

看看isEqual:compare:的方法。

0

我有以下对象:

#import <Foundation/Foundation.h> 

typedef NS_ENUM(NSUInteger, SeasonType) { 
    kWinter, 
    kSpring, 
    kSummer, 
    kFall 
}; 

@interface Season : NSObject 

@property (nonatomic) SeasonType season; 
@property (nonatomic) NSUInteger year; 

+(id) seasonWithYear:(NSInteger)year season:(SeasonType)season; 
-(id) initWithYear:(NSInteger)year season:(SeasonType)season; 

@end 

我要做的就是改写基地NSObject的比较方法,就没有必要重新发明轮子和代码保持清洁,以及:

#import "Season.h" 

@interface Season() 

@end 

@implementation Season 

+(id) seasonWithYear:(NSInteger)year season:(SeasonType)season{ 
    return [[self alloc] initWithYear:year season:season]; 
} 

-(id) initWithYear:(NSInteger)year season:(SeasonType)season{ 
    self = [super init]; 
    if (self) 
    { 
     _year = year; 
     _season=season; 
     _baseDate=nil; 
    } 

    return self; 
} 

#pragma mark - NSObject 

- (BOOL)isEqual:(id)object { 
    if (self == object) { 
     return YES; 
    } 

    if (![object isKindOfClass:[Season class]]) { 
     return NO; 
    } 

    return [self _isEqualToSeason:(Season *)object]; 
} 

- (NSUInteger)hash { 
    return self.season^self.year; 
} 


#pragma mark - Private/Internal 

- (BOOL)_isEqualToSeason:(Season *)season { 
    if (!season) { 
     return NO; 
    } 

    return ((!self.season && !season.season) || self.season == season.season) && 
    ((!self.year && !season.year) || self.year == season.year) ; 
} 

@end 

用法:

Season *season2 = [Season seasonWithYear:2010 season:kFall]; 
Season *season3 = [Season seasonWithYear:2009 season:kFall]; 
[season2 isEqual:season3];