如何在 Objective-C 中正确地覆盖 isEqual:
? “捕获”似乎是如果两个对象相等(由 isEqual:
方法确定),它们必须具有相同的哈希值。
Introspection Cocoa Fundamentals Guide 的部分确实有一个关于如何覆盖 isEqual:
的示例,复制如下,用于名为 MyWidget
的类:
- (BOOL)isEqual:(id)other {
if (other == self)
return YES;
if (!other || ![other isKindOfClass:[self class]])
return NO;
return [self isEqualToWidget:other];
}
- (BOOL)isEqualToWidget:(MyWidget *)aWidget {
if (self == aWidget)
return YES;
if (![(id)[self name] isEqual:[aWidget name]])
return NO;
if (![[self data] isEqualToData:[aWidget data]])
return NO;
return YES;
}
它检查指针相等,然后是类相等,最后使用 isEqualToWidget:
比较对象,它只检查 name
和 data
属性.示例没有展示的是如何覆盖hash
。
假设还有其他不影响相等性的属性,比如 age
。不应该重写 hash
方法,使得只有 name
和 data
影响哈希?如果是这样,你会怎么做?只需添加 name
和 data
的哈希?例如:
- (NSUInteger)hash {
NSUInteger hash = 0;
hash += [[self name] hash];
hash += [[self data] hash];
return hash;
}
够了吗?有没有更好的技术?如果你有像 int
这样的原语怎么办?将它们转换为 NSNumber
以获取它们的哈希?或者像 NSRect
这样的结构?
(Brain fart:最初将它们与|=
一起写成“按位或”。意思是添加。)
最佳答案
开始
NSUInteger prime = 31;
NSUInteger result = 1;
那么对于你所做的每一个原语
result = prime * result + var
对于对象,您使用 0 表示 nil,否则使用它们的哈希码。
result = prime * result + [var hash];
对于 bool 值,您使用两个不同的值
result = prime * result + ((var)?1231:1237);
这不是 tcurdt 的作品,评论要求更多解释,所以我认为编辑署名是公平的。
该算法在《Effective Java》一书中得到普及,the relevant chapter can currently be found online here .那本书普及了该算法,现在该算法已成为许多 Java 应用程序(包括 Eclipse)的默认设置。然而,它源自一个更古老的实现,该实现被各种归因于 Dan Bernstein 或 Chris Torek。那个较旧的算法最初在 Usenet 上流传,并且很难确定归属。比如有一些interesting commentary in this Apache code (搜索他们的名字)引用原始来源。
底线是,这是一个非常古老、简单的散列算法。它不是性能最好的,甚至在数学上也没有被证明是一个“好”的算法。但是简单,很多人用了很久,效果也不错,所以有很多历史支持。
https://stackoverflow.com/questions/254281/
相关文章:
objective-c - 将 NSDate 转换为 NSString
ios - 如何以编程方式确定我的应用程序是否在 iphone 模拟器中运行?
objective-c - 对于 Objective-C 中用于访问 NSMutable 字典的每个
ios - 不能在 Objective-C 中使用 Swift 类
ios - 总是将 self 的弱引用传递到 ARC 中的 block 中?
ios - 解释 iOS7 中自动调整 ScrollView 插入、扩展布局包含不透明条、边缘For
objective-c - 问号和冒号是什么意思(?: ternary operator) mean