Есть ли что-то вроде общего списка в Какао / Objective-C? - PullRequest
30 голосов
/ 27 апреля 2009

Что мне действительно нравится в C #, так это общие списки. Список, который может содержать только один тип объектов. Есть ли что-то вроде общего списка в Какао / Objective-C? Насколько я знаю только NSArray, кто возьмет указатель на любой объект.

Ответы [ 4 ]

34 голосов
/ 27 апреля 2009

Желание этого в приложении Какао часто является признаком слабого дизайна.

NSArray является неизменным, поэтому он не «берет указатель на какой-либо объект» и, по-видимому, уже содержит правильные объекты при передаче вам. Я предполагаю, что вас больше всего беспокоит NSMutableArray, где вы думаете, что другие части вашего кода могут добавить неправильный тип объекта. Но взгляните на само Какао; невероятно редко выставлять изменяемый массив как часть дизайна класса.

Вместо этого вы обычно предоставляете NSArray и несколько методов для изменения этого массива. Что-то вроде:

@class Foo : NSObject
- (NSArray *)bars;
- (void)addBar:(Bar *)bar;
- (void)removeBar:(Bar *)bar;
@end

Как правило, это останавливает вставку неправильных объектов просто при наличии предупреждения компилятора, и, конечно, вы можете добавить утверждения в -addBar: и -removeBar:, если хотите, тоже.

9 голосов
/ 27 апреля 2009

Objective-C не поддерживает общее программирование. Вы всегда можете использовать Objective-C ++ и список STL.

3 голосов
/ 14 марта 2013

Общие NSArrays могут быть реализованы путем создания подкласса NSArray и переопределения всех предоставленных методов с более ограничительными. Например,

- (id)objectAtIndex:(NSUInteger)index

должно быть переопределено в

@interface NSStringArray : NSArray

в

- (NSString *)objectAtIndex:(NSUInteger)index

для NSArray, содержащего только строки NSS.

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

Можно автоматизировать это и свести к минимуму два утверждения, что приближает его к языкам, которые поддерживают дженерики. Я создал автоматизацию с помощью WMGenericCollection , где шаблоны предоставляются в виде макросов препроцессора C.

После импорта файла заголовка, содержащего макрос, вы можете создать универсальный NSArray с двумя операторами: один для интерфейса и один для реализации. Вам нужно только указать тип данных, которые вы хотите сохранить, и имена для ваших подклассов. WMGenericCollection предоставляет такие шаблоны для NSArray, NSDictionary и NSSet, а также их изменяемые аналоги.

0 голосов
/ 01 августа 2013

Нет, Objective-C в настоящее время не поддерживает параметрическую типизацию для элементов коллекции.

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

Параметрическая типизация для коллекций в Objective-C будет отличаться от Generics в C # / Java. Например, маловероятно, что вы когда-нибудь увидите, как Objective-C добавит возможность гарантировать, что каждый объект, добавленный в коллекцию IS , имеет тип или подтип NSArray. Вместо этого Objective-C может (и IMO должен) иметь возможность обеспечить каждый объект в коллекции CONFORMS протоколом / интерфейсом. (то есть, что он реализует набор необходимых методов)

Почему?

Objective-C - это язык, построенный на совместимости с протоколом (интерфейсом), а не на отношениях подтипов. То есть объекты совместимы, если у них есть все правильные методы, мы не смотрим на их действительные типы или не заботимся о них. На самом деле, смотреть на настоящие типы - очень и очень плохая практика в Obj-C, и это крайне обескураживает. Это понятие иногда называют «Duck Typing», потому что если оно крякает как утка, то это утка. Нам все равно, если оно буквально унаследовано от какой-то конкретной утки или нет. Это препятствует тому, чтобы кто-то оседлал вам иерархию реализации. - В результате, пока объект, выходящий из списка, имеет метод draw :: method, он работает, нам на самом деле все равно, является ли он подклассом какого-то конкретного объекта JimmyDrawableBase.

Это не только делает код более пригодным для повторного использования, но также поощряет несколько иной (более функциональный?) Тип декомпозиции проблем, потому что вы не можете полагаться на объекты, производные от данного базового класса и, таким образом, имеющие кучу ваших реализация базового класса навязана им.

Лично я думаю, что неплохо для компилятора Obj-C иметь параметрическую проверку PROTOCOL * CONFORMANCE *. То есть сделать NSMutableArray, который требует, чтобы все размещенные в нем объекты соответствовали заданному протоколу (т. Е. Иметь заданный набор необходимых методов).

Иногда даже этой более гибкой проверке соответствия протокола сопротивляются люди, занимающиеся динамическим программированием, и по веским причинам. У программистов часто есть способ переопределить требования соответствия.

Например, вам может потребоваться список, содержащий объекты, соответствующие протоколу / интерфейсу NSArray, но вы можете АКТУАЛЬНО вызывать только два из этих методов. Это чрезмерное соответствие. Тот, кто хочет вставить совместимый элемент в ваш массив, вынужден реализовать массу методов, которые вы на самом деле не вызываете - по крайней мере, пока (см. Далее).

Google Go пытается решить эту проблему, делая вывод о структурной совместимости. То есть, если вы вызываете draw () для элементов, выходящих из списка, то компилятор гарантирует, что все входящие в список содержит метод draw (). Если он не содержит метод draw (), это ошибка компилятора, чтобы поместить его в список. Это препятствует тому, чтобы код просто вызывал ту же ошибку во время выполнения. Проблема в том, что он работает только для компиляции всей программы. Если Google-Go может скомпилировать модульные библиотеки DLL (чего не может), то возникнет проблема, заключающаяся в том, что я не могу сказать, что объекты в списке должны поддерживать определенный интерфейс из трех методов, даже если Я не звоню им сегодня, потому что я мог бы позвонить им в будущем .

Между этими двумя решениями нравится обмен и правда.

Лично я хотел бы, чтобы Objective-C добавил соответствие параметрического протокола, поэтому я мог бы попросить компилятор обеспечить, чтобы содержимое конкретной коллекции всегда соответствовало заданному набору протоколов.

Мне также хотелось бы, чтобы компилятор помог мне избежать чрезмерного соответствия. Если я не вызываю методы в этих протоколах для объектов, он должен генерировать ошибки / предупреждения, сообщающие мне об этом. Если я хочу сохранить их в протоколе, даже если я их не использую, мне нужно было бы явно сделать объявление для каждого метода в протоколе, что он "может быть использован в будущем, поэтому все элементы должны предоставить его сейчас ». Это, по крайней мере, заставляет процесс избыточного соответствия требовать БОЛЬШЕ работы вместо Java / C #, где требуется меньше работы.

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