Ответ 1
Копия гарантирует, что значения, используемые в качестве ключей, не меняются "underhand" при использовании в качестве ключей. Рассмотрим пример изменяемой строки:
NSMutableString* key = ...
NSMutableDictionary* dict = [[NSMutableDictionary alloc] init];
[dict setObject: ... forKey: key];
Предположим, что словарь не скопировал ключ, а вместо этого просто retain
отредактировал его. Если теперь, в какой-то более поздней момент, исходная строка будет изменена, то очень вероятно, что вы не собираетесь снова найти свое сохраненное значение в словаре, даже если вы используете тот же самый ключевой объект (т.е. Один key
указывает в примере выше).
Чтобы защитить себя от такой ошибки, словарь копирует все ключи.
Обратите внимание, что, кстати, достаточно просто определить -copyWithZone:
как просто выполнение return [self retain]
. Это допустимо и хороший код, если ваш объект неизменен, а контракт NSCopying
специально разработан таким образом, что возвращаемый объект должен быть (sorta, kinda) неизменным:
Реализовать NSCopying, сохранив оригинал вместо создания новой копии, когда класс и его содержимое являются неизменяемыми.
(из Справка NSCopying)
и
Возвращенная копия является неизменной, если рассмотрение вопроса о "неизменяемом и изменяемом" относится к принимающему объекту; в противном случае точный характер копии определяется классом.
Даже если ваши объекты не являются неизменными, вы можете уйти с этой реализацией, если только когда-либо используете реализации равенства/хэша на основе идентификации, то есть реализации, которые никак не затрагиваются внутренним состоянием объекта.