Есть ли что-нибудь вроде общего списка в Cocoa / Objective-C?

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


person TalkingCode    schedule 27.04.2009    source источник
comment
Objective-C - это система, основанная на соответствии протоколу (интерфейсу), а не на отношениях типов. ИМО, вы действительно хотите спросить: есть ли способ для компилятора создать экземпляры типов коллекции, чтобы все элементы коллекции соответствовали заданному протоколу (интерфейсу).   -  person David Jeske    schedule 01.08.2013


Ответы (4)


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

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

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

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

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

person Community    schedule 27.04.2009
comment
Кроме того, если вам нужны более сложные операции, прочтите -mutableArrayValueForKey: - person Mike Abdullah; 28.04.2009
comment
-1 Категорически не согласен - отрицая, что добавление дженериков C # в Objective C приведет к - person Paul Delhanty; 25.07.2012
comment
... явное улучшение. Языковая поддержка строгой и динамической типизации - дополнительные методы. Прогноз: однажды в Objective C будут реализованы обобщения в стиле C #. - person Paul Delhanty; 25.07.2012
comment
Дженерики - это не слабый дизайн, и желание их не является признаком слабого дизайна. Просто они не применимы к Objective-C. Остальная часть вашего ответа полезна, однако вступительное заявление совершенно неверно и вводит в заблуждение. - person Chris Hatton; 27.07.2012
comment
Ну, поскольку это был вопрос о Какао, мой ответ был конкретно о Какао! - person Mike Abdullah; 28.07.2012
comment
Общие списки - прекрасная идея и хороший дизайн. С другой стороны, неоднородные списки - ужасная идея. - person nont; 09.02.2013
comment
Я бы хотел, чтобы в Objective C были дженерики, это помогло бы понять код других людей намного проще. Это экономия времени. Я вообще не считаю это слабым дизайном. - person Daniel Ryan; 11.03.2013
comment
Специалисты по Obj-C и C # / Java спорят друг с другом по этому поводу. Дженерики в стиле Java, которые заставляют коллекции содержать только объекты, производные от определенного базового класса, являются плохой идеей в Objective-C, потому что Obj-C - это язык, основанный на совместимости протоколов (интерфейсов). (Иногда это называется утиной типизацией, потому что если она крякает, как утка, то это утка) ОДНАКО, Obj-C может выиграть от параметрического соответствия протоколу. С помощью этого набора можно было объявить, что разрешены только элементы, соответствующие определенным протоколам. Помогает превратить ошибки времени выполнения в ошибки времени компиляции. - person David Jeske; 01.08.2013
comment
Итак, вы думаете, что это не нужно, и желание этого - признак слабого дизайна. Зачем он вам нужен, если вы можете сделать это самостоятельно, определив вместо этого громоздкий дополнительный класс, вся цель которого - имитировать общий массив (только для одного конкретного типа) во много-много раз большем количестве строк кода? Это кажется невероятно глупым. - person Mark Amery; 05.09.2013
comment
Я не предлагаю людям эффективно воссоздавать большие куски NS(Mutable)Array API на регулярной основе. Обычно требуется всего несколько методов, и они, как правило, являются частью более широкого класса для хранения других свойств. - person Mike Abdullah; 06.09.2013
comment
Я думал, что у List есть улучшения производительности в некоторых сценариях, когда элементы вставляются в середину коллекции. - person drlobo; 04.12.2013
comment
@drlobo звучит так, будто вы думаете о связанном списке? Если так, то это не имеет никакого отношения к рассматриваемой теме. - person Mike Abdullah; 05.12.2013

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

person Ferruccio    schedule 27.04.2009

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

- (id)objectAtIndex:(NSUInteger)index

пришлось бы переопределить в

@interface NSStringArray : NSArray

as

- (NSString *)objectAtIndex:(NSUInteger)index

чтобы NSArray содержал только NSStrings.

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

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

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

person w-m    schedule 14.03.2013
comment
Спасибо, что разместили свой ответ! Не забудьте внимательно прочитать FAQ по саморекламе. Также обратите внимание, что требуется, чтобы вы публиковали отказ от ответственности каждый раз, когда вы ссылаетесь на свой собственный сайт / продукт. - person Andrew Barber; 15.03.2013
comment
Спасибо что подметил это. Я был совершенно не уверен, как это сделать, и не считается ли это рассылкой спама. Сейчас я занят, но через пару часов я доработаю ответы в соответствии с инструкциями. - person w-m; 15.03.2013
comment
Отлично! Ваши последние два ответа достойны, потому что они, кажется, касаются вопроса, вы включили некоторую полезную информацию (не только посмотрите здесь этот проект и список функций). Просто добавьте раскрытие, и они в порядке. еще раз спасибо! Ой, также; просто к вашему сведению; будьте осторожны при размещении точных копий ответов; Они кажутся достаточно хорошими для их вопросов, но обязательно постарайтесь дать ответы на этот вопрос конкретно. - person Andrew Barber; 15.03.2013

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

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

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

Почему?

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

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

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

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

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

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

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

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

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

person Community    schedule 01.08.2013
comment
Фактически, просмотр реальных типов - очень плохая практика в Obj-C и крайне не рекомендуется. Не могли бы вы рассказать об этом подробнее? Все стандартные объекты данных реализованы с помощью наследования, а не протоколов. Возьмем для примера NSDecimalNumber: NSNumber: NSValue: NSObject. Или NSString, который также не предоставляет протокол. Таким образом, из двух параметров времени компиляции isKindOfClass: можно использовать, а corresToProtocol: нельзя. Как это плохая практика? - person w-m; 14.08.2013