我有一组类来表示从数据库加载的一些对象。这些对象有几种变体,所以我有一个共同的基类和两个子类来表示差异。他们共同的一个关键领域是id字段。
不幸的是,对象的id在所有变体中并不是唯一的,而是在单个变体中。我的意思是,类型A的单个对象可以具有介于0和1,000,000之间的ID。类型B的对象可以具有25,000和1,025,000之间的id。这意味着id号有一些重叠。但是,对象只是同类事物的变体,因此我想在我的代码中考虑它们。 (出于遗留原因,他们被分配了来自不同集合的ID。)
所以我有这样的课程:
@class BaseClass
@class TypeAClass : BaseClass
@class TypeBClass : BaseClass
BaseClass有一个方法(NSNumber *)objectId。但是,如上所述,TypeA和TypeB的实例可能有重叠的id,所以当涉及到相等并将它们放入集合中时,我不能仅使用id来检查它。
这些实例的唯一键实际上是(class + objectId)。所以我认为我可以通过在BaseClass上创建以下哈希函数来实现这一点:
-(NSUInteger)hash
{
return (NSUInteger)[self class] ^ [self.objectId hash];
}
我也像这样实现了isEqual:
- (BOOL)isEqual:(id)object
{
return (self == object) || ([object class] == [self class] && [self.objectId isEqual:[object objectId]]);
}
这似乎有效,但我想我只是在这里要求确保我不会忽略某些东西 - 尤其是通过以这种方式使用类指针来生成散列。这样做安全还是有更好的方法吗?
答案 0 :(得分:2)
这可能是安全的,但不一定。如果您实际上以某种方式结束了子类,那么根据严格的类标识可能会咬你(例如,如果KVO导致您的类被切换为另一个*)。如果使用某种明确的类ID,它可能会更安全一些。
另请注意,不相等的对象不需要具有不同的哈希值。唯一的要求是相等的对象必须具有相同的散列。所以如果这两个类中的对象具有相同的哈希值,这是可以的,只要这不会使哈希表的运行速度过快。
(*老实说,如果秘密的KVO子类伪装成父类,我真的不记得了我的头脑,在这种情况下你仍然在这里安全,但我通常会尽量避免依赖类的身份。 )