【问题标题】:What is the NSObject isEqual: and hash default function?什么是 NSObject isEqual: 和 hash 默认函数?
【发布时间】:2010-11-17 12:20:40
【问题描述】:

我有一个NSObject 的数据库模型类。我在NSMutableArray 中有一组这些对象。我使用indexOfObject: 来查找匹配项。问题是模型对象的内存地址发生了变化。所以我重写了hash 方法来返回模型的行ID。然而,这并不能解决它。我还必须重写isEqual: 方法来比较hash 方法的值。

isEqual: 方法默认使用什么来确定相等性?

我假设它使用内存地址。阅读isEqual: 文档后,我认为它使用了hash 方法中的值。显然,情况并非如此,因为我尝试覆盖该值并没有解决我最初的问题。

【问题讨论】:

  • 这里有一些推测性的答案。任何人都可以提供默认 isEquals 使用地址的实际文档吗?我并不是建议它不使用,只是想从马的嘴里听到它。
  • @DougW 我分享了你对此的感受,所以我找到了一份官方参考资料并将其编辑为接受的答案。
  • 您正在阅读 NSObject 协议的文档,而不是 NSObject 类。协议定义了方法应该做什么,类没有定义它实际做什么。覆盖 equals 和 hash 以按照您希望的方式工作总是最安全的。
  • @TerryWilcox 不,它已记录在案,正如接受的答案中所引用的那样。它只是没有记录在您期望的类参考中。绝对没有必要重写isEqual: 来执行与== 的显式指针比较,只是为了安全地传递indexOfObject: 某个任意NSObject 子类的实例——你可以相信NSObjectisEqual: 会做指针比较。
  • @TerryWilcox 我同意关于这一点的文档非常糟糕,但我认为建议您始终覆盖isEqual: 而不要相信NSObject 的实现太过分了。显然,如果指针相等(这是 NSObjectisEqual: 实现检查的内容)实际上不是您想要的,那么您应该覆盖它。

标签: objective-c nsarray nsobject


【解决方案1】:

关于isEqual:的默认实现的答案是综合的。所以我只是添加了关于hash 的默认实现的注释。这里是:

-(unsigned)hash {return (unsigned)self;}

也就是说,它与isEqual: 中使用的指针值相同。以下是您可以查看的方法:

NSObject *obj = [[NSObject alloc] init];
NSLog(@"obj: %@",obj);
NSLog(@"hash: %x",obj.hash);

结果会是这样的:

obj: <NSObject: 0x16d44010>
hash: 16d44010

最好的问候。

顺便说一句,在 iOS 8 中 hash 变成了属性而不是方法,但它就在那里。

【讨论】:

    【解决方案2】:

    正如您猜对的,NSObject 的默认isEqual: 行为是比较对象的内存地址。奇怪的是,NSObject Class Reference 中目前没有记录,但Introspection 文档中记录了它,其中指出:

    isEqual: 的默认 NSObject 实现只检查指针是否相等。

    当然,如您所知,NSObject 的子类可以覆盖 isEqual: 以表现不同。例如,NSStringisEqual: 方法在传递另一个 NSString 时,将首先检查地址,然后检查字符串之间的精确文字匹配。

    【讨论】:

    • 有这方面的参考就好了。
    • ...所以我加了一个。奇怪的是,NSObject 类引用甚至没有 isEqual: 的条目,更不用说在任何地方描述它的行为,这似乎是一个明显的遗漏。不过,我能够在文档的“概念”部分的某个不起眼的页面中找到官方参考资料。
    • Apple 文档中充斥着协议方法未记录在类文档中的情况。 (更不用说超类方法了。)您经常不得不在大量的岩石下寻找给定方法的文档。
    • (我希望 Apple 的文档更像 Java 的文档,其中所有继承的方法至少都与类的描述一起列出。)
    【解决方案3】:

    我假设NSObject isEquals 使用== 运算符,hash 使用内存地址。

    isEquals 方法永远不应使用hash 作为相等性的绝对测试。如果您搜索足够多的对象(只需创建超过 2^32 个不同的对象,其中至少两个将具有相同的hash),就可以保证有两个对象具有相似的hashCode

    换句话说,hash 需要以下规范:如果两个对象相等,那么它们的hash 需要相等;但是,如果两个对象的hash 值相等,则它们不一定相等。

    作为提示,您应该始终同时覆盖 isEqualshashCode

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-12
      • 2023-03-14
      • 2010-09-20
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多