本文共 2527 字,大约阅读时间需要 8 分钟。
在软件开发中,无论使用何种语言,比较两个对象是否相等都至关重要。OC也不例外。我们从最基本的 NSString 比较开始,逐步深入探讨对象等同性的实现原理。
假设我们有以下代码:
NSString *str1 = [[NSString alloc] initWithCString:"equal" encoding:NSUTF8StringEncoding];NSString *str2 = @"equal";if (str1 == str2) { NSLog(@"equal");} 这段代码看似简单,但运行结果却令人困惑。尽管 str1 和 str2 表面上看起来相等,但由于比较的是对象指针的相等性,而不是实际的字符串内容,导致结果总是 false。
为了正确比较两个字符串,我们应该使用 isEqual: 方法:
NSString *str1 = [[NSString alloc] initWithCString:"equal" encoding:NSUTF8StringEncoding];NSString *str2 = @"equal";if ([str1 isEqual:str2]) { NSLog(@"equal");} 这里 isEqual: 方法在 NSString 类中被精细实现,真正比较的是字符串内容,而不是对象指针。因此,输出 "equal" 是正确的。
为了更深入理解,我们可以创建一个自定义类 EqualObject,并实现 isEqual: 方法。
@interface EqualObject : NSObject@property (nonatomic, strong) NSString *name;@end@implementation EqualObject@end
创建两个 EqualObject 实例并比较:
EqualObject *object1 = [EqualObject new];EqualObject *object2 = [EqualObject new];if ([object1 isEqual:object2]) { NSLog(@"equal");} 此时,输出结果仍为 false,因为 isEqual: 方法的默认实现是比较对象指针是否相同。因此,我们需要自定义 isEqual: 方法:
-(BOOL)isEqual:(id)object { if ([self class] == [object class]) { if (![self.name isEqual:object.name]) { return NO; } return YES; } else { return [super isEqual:object]; }} 这段代码首先检查对象的类别是否相同,然后比较 name 属性。如果 name 相同,返回 true,否则返回 false。
为了更精确地控制等同性,我们可以为 EqualObject 类添加定制的 isEqualToEqualObject: 方法:
-(BOOL)isEqualToEqualObject:(EqualObject *)object { if (self == object) { return YES; } if (![self.name isEqualToString:object.name]) { return NO; } return YES;}-(BOOL)isEqual:(id)object { if ([self class] == [object class]) { return [self isEqualToEqualObject:object]; } else { return [super isEqual:object]; }} 客户端代码变为:
if ([object1 isEqualToEqualObject:object2]) { NSLog(@"equal");} 这样可以更明确地比较对象的等同性。
每个 OC 对象都有一个 hash 方法,用于计算对象的哈希值。集合(如 NSArray、NSSet 等)使用哈希值来存储对象,以提高存取效率。
-(NSUInteger)hash { NSUInteger nameHash = [_name hash]; return nameHash;} 如果对象的 hash 值相同,但对象内容不同,可能导致潜在的冲突。为了避免这种情况,我们可以自定义 hash 方法:
-(NSUInteger)hash { NSUInteger nameHash = [_name hash]; NSUInteger ageHash = _age; return nameHash ^ ageHash;} 对于 NSArray,isEqual: 方法默认比较每个元素的位置:
NSArray *array1 = @[object1, object2];NSArray *array2 = @[object1, object2];if ([array1 isEqual:array2]) { NSLog(@"equal");} 如果数组中的元素位置相同且每个元素相等,数组才被认为相等。
在使用集合(如 NSSet)时,需注意其 isEqual: 和 hash 方法的行为。为了避免冲突,应确保所有对象的 hash 值和内容都唯一。
通过以上方法,我们可以更好地理解和实现对象等同性的原理,从而在实际开发中更高效地管理对象比较和存储。
转载地址:http://gynfk.baihongyu.com/