2009-08-19 2 views
7

Мне интересно, почему Apple использует (довольно сильно в CoreAnimation, но где-то еще) константы, объявленные как NSString * const, например, kCAGravityTop вместо обычных перечислений? Как насчет безопасности типов в этом случае? Насколько я понимаю, любой NSString можно передать методу, ожидающему эту константу, без каких-либо предупреждений компилятора.Причины использования констант NSString над перечислениями?

ответ

11

Я не уверен, но я предполагаю, что это связано с тем, что пользователи добавили свои собственные расширения и подклассы к некоторым материалам Apple. В этом случае вы можете просто переопределить использованный метод и поймать случай, когда строка «MyOwnValue», а затем делать с ней все, что вы хотите. Это значительно проще, чем изменение переименования Apple, и это также мешает вам что-то прикручивать.

Возможно, это также упростит независимость версии от Apple. С перечислениями, если вы каким-то образом измените порядок, это может вызвать множество проблем для любых их значений, которые были кэшированы (по какой-либо причине). Если значение enum равно 1 < < 3, когда оно сохраняется в файле, тогда Apple добавляет еще одно перечисление, так что его значение теперь 1 < < 4, то очевидно, что неправильная вещь выходит из вашей программы. Почему бы им не быть осторожными при перемещении значений enum, я не знаю, но я думаю, что вполне вероятно, что они использовали NSString, потому что нет никакой возможности изменить его значение или порядок в любой версии.

+0

+1 Хорошая гипотеза – h4xxr

+0

Кроме того, я считаю, что архивирование и разборки являются фактором.Теперь, когда фреймворки, такие как Core Data, используются гораздо шире, вы обнаруживаете, что, если используются перечисления, существует много бокса и unboxing, которые могут быть просто учтены, если строки используются вместо этого, хотя некоторые соображения все еще остаются для строковых констант - бремя ненужных «сантехника» снижается. – TheBasicMind

7

Я подозреваю, что причина историческая или стилистическая больше всего на свете. Вот как это сделали структуры NeXT, и это создало «стиль» какао. Как преимущество этого подхода, проверка значения в отладчике может дать значимое значение (например, @ «CAGravityTop» или что-то вроде этого вместо бессмысленного int). Поскольку статические строки обрабатываются компилятором разумно, сравнение может быть связано с сопоставлением указателей, а не с равенством строк (см. Ответ bbum), поэтому для этого подхода наблюдается незначительная производительность.

9

Перечисленные типы не могут быть расширены без добавления дополнительных записей в самом перечисляемом типе. Таким образом, невозможно иметь содержимое перечисления, которое обрабатывается как формальный член перечисляемого типа, но также не отображается во время обычной компиляции.

Возьмите CoreAnimation, например. Могут существовать значения, которые используются внутри, которые не поддерживаются или не доступны через публичный API по целому ряду причин; «информация о реализации» сразу приходит на ум.

Кроме того, строки как константы допускают расширение, как подразумевает Эли. Они также имеют тенденцию быть более информативными при отладке. «kCAGravityTop» является гораздо более показательным, чем, скажем, «4».

С точки зрения производительности, очень мало штрафов за использование строк. Статические строки, из которых внутренняя копия каждой внешней декларации почти каждой строковой константы фактически состоит из, эффективно обрабатываются компилятором, а первый тест метода -isEqualToString: равенство указателя - очень быстро. Не так быстро, как switch(), но при условии величины выполнения кода, подразумеваемой константой, разница в нескольких циклах между switch() и сопоставлением строк не имеет значения.

5

Еще одна причины, я думал в пользу NSString является то, что он может роздан везде, где id принимается (например, как userInfo или как словарные ключей), а примитивные типам (перечисления) будут нужны какое-то обертка для этого

Смежные вопросы