Какова логика наличия изменчивых и неизменных версий классов, таких как NSArray, NSDictionary и т. Д. В Objective C? - PullRequest
20 голосов
/ 04 июля 2011

Почему общие классы коллекций в Objective C, такие как NSString, NSArray, NSDictionary и т. Д., Имеют как изменяемую, так и неизменную версию. Какова логика определения их отдельно? Производительность, управление памятью или что-то еще?

Ответы [ 5 ]

14 голосов
/ 04 июля 2011

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

Кроме того, неизменность означает, что изменение не может произойти после того, как государство было распущено. Например, метод NSView subviews возвращает неизменный массив, таким образом гарантируя, что вызывающая сторона не будет играть в игры с содержимым (и даже не ожидать, что сможет). Внутренне, NSView может решить вернуть [вероятный] NSMutableArray, который содержит подпредставления (так как он является внутренне изменяемым), и приведение типа к NSArray означает, что вызывающая сторона не может манипулировать содержимым без зла предупреждение о том, что составитель или плохой компилятор. (Между прочим, это может быть, а может и не быть реальной реализацией, но этот шаблон используется в другом месте).

Неизменяемость также означает, что перечисление и / или обход могут выполняться без риска изменения состояния в середине. Точно так же многие неизменяемые классы также явно поточно-ориентированы; любое количество потоков может одновременно прочитать неизменяемое состояние, часто без необходимости блокировки.

12 голосов
/ 04 июля 2011

В общем случае для API неизменяемый класс будет поточно-ориентированным, поэтому вы можете читать его непосредственно в фоновом потоке, не беспокоясь, что его содержимое изменится ...

Это имеет большее значение для таких вещей, какколлекция, в которой содержимое может сместиться, и вы можете быть в процессе их перечисления.

10 голосов
/ 04 июля 2011

Почему общие классы коллекций в Objective C, такие как NSString, NSArray, NSDictionary и т. Д., Имеют как изменяемую, так и неизменную версию.

эта концепция используется в родственных языках. заметное различие заключается в том, что типы объектов называются изменяемыми вариантами. Подобные языки обычно достигают этого с помощью ключевого слова, такого как const. конечно, другие родственные языки также используют типы, которые являются явно изменяемыми или неизменяемыми.

Какова логика определения их отдельно?

В сообщениях objc не различаются const и non-const, а язык не предоставляет встроенной поддержки для гарантии того, что состояние объекта не изменится (хотя это действительно не будет сложным дополнением, если вы действительно склонны расширять компилятор) , так что здесь тоже немного истории.

поэтому для класса принято определять неизменяемость и изменчивость и предоставлять варианты, которые различают изменчивость.

множественные абстракции также вводят безопасность типов и намерение.

Производительность

да. Есть несколько оптимизаций, которые может выполнить инвариантный объект.

в некоторых случаях:

  • он может кэшировать значения, никогда не вычисляя их более одного раза.
  • он мог бы использовать точные, неизменяемые выделения для своих данных.
  • он часто не требует специального кода для многопоточного использования - многие неизменяемые типы будут видоизменяться только во время строительства / разрушения.
  • эти типы часто используют кластеры классов. если реализован кластер классов, то специализированные реализации могут обеспечить существенные различия в памяти, реализации и т. д., учитывая, как неизменная строка с ровно одним символом может отличаться от изменяемого варианта.

управление памятью

в некоторых случаях:

  • неизменяемые типы могут делиться своим неизменным содержимым.
  • они также могут сократить ассигнования. например, реализация copyWithZone: или initWithType: может вернуть сохраненный источник, а не глубокую или поверхностную физическую копию.

или что-нибудь еще?

это облегчает написание понятных интерфейсов. Вы можете гарантировать и (пытаться) ограничивать некоторые вещи. если бы все было изменчиво, было бы еще много ошибок и особых случаев. фактически это различие может полностью изменить подход к написанию библиотек objc:

[[textField stringValue] appendString:@" Hz"];
[textField stateDidChange];

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

8 голосов
/ 04 июля 2011

По сути, когда вы знаете, что структура данных неизменна, вы можете сделать много оптимизаций вокруг этого.Например, если массив является неизменяемым, вы можете опустить весь код, который будет «наращивать» массив при каждой попытке добавить объект, и вы можете просто сделать свой неизменяемый массив оболочкой вокруг id[]. * 1002.*

0 голосов
/ 17 апреля 2017

Помимо ответов, упомянутых выше, есть одно отличие: Неизменяемые объекты обычно безопасны для потоков. Принимая во внимание, что изменяемые объекты не являются потокобезопасными.

спасибо

...