Что мне действительно нравится в C #, так это общие списки. Список, который может содержать только один тип объектов. Есть ли что-то вроде общего списка в Cocoa / Objective-C? Пока я знаю только NSArray
, кто возьмет указатель на любой объект.
Есть ли что-нибудь вроде общего списка в Cocoa / Objective-C?
Ответы (4)
Желание этого в приложении Какао часто является признаком слабого дизайна.
NSArray
является неизменяемым, поэтому он не будет «принимать указатель на какой-либо объект» и, предположительно, уже содержит правильные объекты при передаче вам. Я предполагаю, что вас больше беспокоит NSMutableArray
, когда вы думаете, что другие части вашего кода могут добавить объект неправильного типа. Но взгляните на сам Какао; невероятно редко открывать изменяемый массив как часть дизайна класса.
Вместо этого вы обычно предоставляете NSArray
и несколько методов для изменения этого массива. Что-то вроде:
@class Foo : NSObject
- (NSArray *)bars;
- (void)addBar:(Bar *)bar;
- (void)removeBar:(Bar *)bar;
@end
Обычно это предотвращает вставку неправильных объектов просто благодаря предупреждению компилятора, а затем, конечно, вы можете добавлять утверждения в -addBar:
и -removeBar:
, если хотите.
NS(Mutable)Array
API на регулярной основе. Обычно требуется всего несколько методов, и они, как правило, являются частью более широкого класса для хранения других свойств.
- person Mike Abdullah; 06.09.2013
Objective-C не поддерживает универсальное программирование. Вы всегда можете использовать Objective-C ++ и список STL.
Универсальные массивы 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
, а также их изменяемые аналоги.
Нет, 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 #, где он требует меньше работы.