Я новичок в программировании Mac / iPhone и Objective-C. В C # и Java есть «дженерики», классы коллекций, члены которых могут быть только объявленного типа. Например, в C #
Dictionary<int, MyCustomObject>
могут содержать только ключи, которые являются целыми числами, и значениями типа MyCustomObject. Есть ли аналогичный механизм в Objective-C?
Ответы:
В Xcode 7 Apple представила «Облегченные обобщения» для Objective-C. В Objective-C они будут генерировать предупреждения компилятора, если есть несоответствие типа.
NSArray<NSString*>* arr = @[@"str"]; NSString* string = [arr objectAtIndex:0]; NSNumber* number = [arr objectAtIndex:0]; // Warning: Incompatible pointer types initializing 'NSNumber *' with an expression of type 'NSString *'
А в коде Swift они выдадут ошибку компилятора:
var str: String = arr[0] var num: Int = arr[0] //Error 'String' is not convertible to 'Int'
Легкие универсальные шаблоны предназначены для использования с NSArray, NSDictionary и NSSet, но вы также можете добавить их в свои собственные классы:
@interface GenericsTest<__covariant T> : NSObject -(void)genericMethod:(T)object; @end @implementation GenericsTest -(void)genericMethod:(id)object {} @end
Objective-C будет вести себя так же, как раньше, с предупреждениями компилятора.
GenericsTest<NSString*>* test = [GenericsTest new]; [test genericMethod:@"string"]; [test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
но Swift полностью игнорирует общую информацию. (Больше не так в Swift 3+.)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'
Взаимодействие с API Objective-C
источник
MyClass <Foo: id<Bar>>
, ваш код Swift будет предполагать, что значения являются типом вашего ограничения, что дает вам то, с чем можно работать. Однако специализированные подклассыMyClass
будут игнорировать свои специализированные типы (фактически, они будут рассматриваться как универсальныеMyClass
). См. Github.com/bgerstle/LightweightGenericsExampleНет, в Objective-C нет универсальных шаблонов, если вы не хотите использовать шаблоны C ++ в своих собственных классах коллекции (что я категорически не рекомендую).
Objective-C имеет динамическую типизацию в качестве функции, что означает, что среда выполнения не заботится о типе объекта, поскольку все объекты могут получать сообщения. Когда вы добавляете объект во встроенную коллекцию, они рассматриваются как типовые
id
. Но не волнуйтесь, просто отправляйте сообщения этим объектам как обычно; он будет работать нормально (если, конечно, один или несколько объектов в коллекции не отвечают на отправляемое вами сообщение) .Обобщения необходимы в таких языках, как Java и C #, потому что они являются сильными, статически типизированными языками. Совершенно другая игра, чем функция динамической печати в Objective-C.
источник
Нет, но для большей ясности вы можете прокомментировать его, указав тип объекта, который вы хотите сохранить. Я видел это несколько раз, когда вам нужно написать что-то на Java 1.4 в наши дни) например:
NSMutableArray* /*<TypeA>*/ arrayName = ....
или
NSDictionary* /*<TypeA, TypeB>*/ dictionaryName = ...
источник
В Objective-C нет дженериков.
Из Документов
источник
Apple добавила дженерики в ObjC в XCode 7:
@property NSArray<NSDate *>* dates; - (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date; - (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;
см. здесь: https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61
источник
Это было выпущено в Xcode 7 (наконец-то!)
Обратите внимание, что в коде Objective C это просто проверка во время компиляции; не будет ошибок времени выполнения только из-за помещения неправильного типа в коллекцию или присвоения типизированному свойству.
Объявляем:
@interface FooClass <T> : NSObject @property (nonatomic) T prop; @end
Использование:
FooClass<NSString *> *foo = [[FooClass alloc] init]; NSArray<FooClass<NSString *> *> *fooAry = [NSArray array];
Будьте осторожны
*
с этими s.источник
Общие NSArrays могут быть реализованы путем создания подклассов
NSArray
и переопределения всех предоставленных методов с помощью более ограничительных. Например,- (id)objectAtIndex:(NSUInteger)index
пришлось бы переопределить в
@interface NSStringArray : NSArray
в качестве
- (NSString *)objectAtIndex:(NSUInteger)index
чтобы NSArray содержал только NSStrings.
Созданный подкласс может использоваться в качестве замены и предоставляет множество полезных функций: предупреждения компилятора, доступ к свойствам, улучшенное создание кода и завершение в Xcode. Все это функции времени компиляции, нет необходимости переопределять фактическую реализацию - методы NSArray все еще можно использовать.
Это можно автоматизировать и свести к двум операторам, что приближает его к языкам, поддерживающим дженерики. Я создал автоматизацию с помощью WMGenericCollection , где шаблоны предоставляются как макросы препроцессора C.
После импорта файла заголовка, содержащего макрос, вы можете создать общий массив NSArray с двумя операторами: один для интерфейса, а другой - для реализации. Вам нужно только указать тип данных, который вы хотите сохранить, и имена для ваших подклассов. WMGenericCollection предоставляет такие шаблоны
NSArray
,NSDictionary
иNSSet
, как и их коллеги изменяемые.Пример:
List<int>
может быть реализован с помощью настраиваемого класса с именемNumberArray
, который создается с помощью следующего оператора:WMGENERICARRAY_INTERFACE(NSNumber *, // type of the value class // generated class names NumberArray, MutableNumberArray)
После того, как вы создали
NumberArray
, вы можете использовать его везде в своем проекте. В нем отсутствует синтаксис<int>
, но вы можете выбрать свою собственную схему именования, чтобы пометить их как классы как шаблоны.источник
Взгляни на:
https://github.com/tomersh/Objective-C-Generics
Похоже, что это что-то вроде дженерика для бедняков, перепрофилировавшего механизм проверки протокола.
источник
Теперь мечты сбываются - с сегодняшнего дня в Objective-C есть Generics (спасибо, WWDC). Это не шутка - на официальной странице Swift:
И изображение, подтверждающее это:
источник
Просто хочу прыгнуть сюда. Я написал сообщение в блоге здесь о дженериков.
Я хочу внести свой вклад в то, что Generics можно добавлять в любой класс. , а не только в классы коллекции, как указывает Apple.
Затем я успешно добавил к множеству классов, поскольку они работают точно так же, как коллекции Apple. т.е. проверка времени компиляции, завершение кода, включение удаления приведения типов и т. д.
Наслаждаться.
источник
Классы коллекций, предоставляемые фреймворками Apple и GNUStep, являются полуобобщенными в том смысле, что они предполагают, что им предоставлены объекты, некоторые из которых можно сортировать, а некоторые отвечают на определенные сообщения. Для примитивов, таких как числа с плавающей запятой, целые числа и т. Д., Вся структура массивов C не повреждена и может использоваться, и для них есть специальные объекты-оболочки для использования в общих классах коллекций (например, NSNumber). Кроме того, класс Collection может быть разделен на подклассы (или специально модифицирован с помощью категорий), чтобы принимать объекты любого типа, но вы должны написать весь код обработки типов самостоятельно. Сообщения могут быть отправлены любому объекту, но должны возвращать null, если это не подходит для объекта, или сообщение должно быть отправлено соответствующему объекту. Ошибки истинного типа следует обнаруживать во время компиляции, а не во время выполнения. Во время выполнения они должны обрабатываться или игнорироваться. Наконец, Objc предоставляет средства отражения во время выполнения для обработки сложных случаев, а ответ на сообщение, конкретный тип и службы могут быть проверены на объекте перед отправкой сообщения или помещением в несоответствующую коллекцию. Помните, что разные библиотеки и фреймворки принимают разные соглашения относительно того, как их объекты ведут себя при отправке сообщений, для которых у них нет кодовых ответов, поэтому RTFM. За исключением игрушечных программ и отладочных сборок, большинство программ не должны аварийно завершаться, если они действительно не облажаются и не попытаются записать неверные данные в память или на диск, выполнить недопустимые операции (например, разделить на ноль, но это тоже можно поймать) или получить запрещает системные ресурсы. Динамизм и время выполнения Objective-C позволяют изящно выходить из строя и должны быть встроены в ваш код. (ПОДСКАЗКА) если у вас проблемы с универсальностью ваших функций, попробуй некоторую конкретность. Напишите функции определенными типами и позвольте среде выполнения выбирать (вот почему они называются селекторами!) Соответствующую функцию-член во время выполнения.
Example: -(id) sort (id) obj; // too generic. catches all. // better -(id) sort: (EasilySortableCollection*) esc; -(id) sort: (HardToSortCollection*) hsc; ... [Sorter sort: MyEasyColl]; [Sorter sort: MyHardColl];
источник