你如何在 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
这样的结构?( 脑屁 :最初将它们与
|=
一起写成“按位或”。意思是添加。) 最佳答案
从...开始
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(搜索他们的名字)引用了原始来源。
底线是,这是一个非常古老、简单的散列算法。它不是性能最好的,甚至在数学上也没有证明它是一个“好”的算法。但是它很简单,而且很多人长期使用,效果很好,所以有很多历史支持。
关于objective-c - 覆盖 isEqual : and hash 的最佳实践,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/254281/