Это безопасная / действительная реализация метода хеширования? - PullRequest
2 голосов
/ 29 марта 2010

У меня есть набор классов для представления некоторых объектов, загруженных из базы данных. Существует несколько вариантов этих объектов, поэтому у меня есть общий базовый класс и два подкласса для представления различий. Одним из ключевых общих полей является поле идентификатора.

К сожалению, идентификатор объекта не уникален во всех вариациях, но в пределах одной вариации. Я имею в виду, что один объект типа A может иметь идентификатор, скажем, от 0 до 1 000 000. Объект типа B может иметь идентификатор от 25 000 до 1 025 000. Это означает, что есть некоторые совпадения номеров идентификаторов. Однако объекты - это всего лишь вариации одного и того же вида вещей, поэтому я хочу думать о них как таковых в своем коде. (Им были присвоены идентификаторы из разных наборов по устаревшим причинам.)

Итак, у меня есть такие классы:

@class BaseClass
@class TypeAClass : BaseClass
@class TypeBClass : BaseClass

BaseClass имеет метод (NSNumber *) objectId. Однако экземпляры TypeA и TypeB могут иметь перекрывающиеся идентификаторы, как обсуждалось выше, поэтому, когда дело доходит до равенства и размещения их в наборах, я не могу просто использовать один идентификатор для его проверки.

Уникальный ключ этих экземпляров, по сути, (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]]);
}

Кажется, это работает, но я предполагаю, что я просто прошу здесь убедиться, что я ничего не пропускаю - особенно с генерацией хэша с использованием указателя класса таким образом. Это безопасно или есть лучший способ сделать это?

1 Ответ

2 голосов
/ 29 марта 2010

Это, вероятно, безопасно, но не обязательно. В зависимости от строгой идентичности класса вы можете укусить вас, если вы действительно каким-то образом попадаете на один подкласс (например, если KVO вызывает переключение вашего класса на другой *). Возможно, было бы немного безопаснее, если использовать какой-то явный идентификатор класса.

Также имейте в виду, что неодинаковые объекты не должны иметь разные хэши. Единственное требование состоит в том, что равные объекты должны иметь одинаковый хэш. Так что все в порядке, если объекты в этих двух классах имеют одинаковый хэш, если это не приводит к слишком сильному замедлению ваших хеш-таблиц.

(* Я, честно говоря, не припомню, если секретный подкласс KVO маскируется под родительский класс, и в этом случае вы все еще в безопасности, но я обычно стараюсь избегать зависимости от идентичности класса. )

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...