Czy w Objective-C są mocno wpisane Kolekcje?

Jestem nowy w programowaniu Mac/iPhone i Objective-C. W C# i Javie mamy "generics", klasy kolekcji, których członkowie mogą być tylko zadeklarowanego typu. Na przykład w C #

Dictionary<int, MyCustomObject>

Może zawierać tylko klucze, które są liczbami całkowitymi i wartości, które są typu MyCustomObject. Czy podobny mechanizm istnieje w Objective-C?

Author: Quinn Taylor, 2009-05-11

11 answers

W Xcode 7, Apple wprowadziło 'Lightweight Generics' do Objective-C. W Objective-C, będą one generować ostrzeżenia kompilatora, jeśli wystąpi niedopasowanie typu.

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 *'

I w kodzie Swift wygenerują błąd kompilatora:

var str: String = arr[0]
var num: Int = arr[0] //Error 'String' is not convertible to 'Int'

Lightweight Generics są przeznaczone do użycia z NSArray, NSDictionary i NSSet, ale można je również dodać do własnych klas:

@interface GenericsTest<__covariant T> : NSObject

-(void)genericMethod:(T)object;

@end

@implementation GenericsTest

-(void)genericMethod:(id)object {}

@end

Objective-C będzie zachowywał się tak jak poprzednio z ostrzeżeniami kompilatora.

GenericsTest<NSString*>* test = [GenericsTest new];

[test genericMethod:@"string"];
[test genericMethod:@1]; // Warning: Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString *'
/ Align = "Left" / całkowicie zignoruje Ogólne informacje. (Nie jest już prawdą w Swift 3+.)
var test = GenericsTest<String>() //Error: Cannot specialize non-generic type 'GenericsTest'

Oprócz tych podstawowych klas zbiorów, Objective-C lightweight generics są ignorowane przez Swift. Wszystkie inne typy wykorzystujące lekkie leki generyczne są importowane do Swift tak, jakby były nieparametryzowane.

Interakcja z API Objective-C

 206
Author: Connor,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-01 16:52:30

Ta odpowiedź jest nieaktualna, ale pozostaje dla wartości historycznej. Od Xcode 7, odpowiedź Connora z 8 czerwca ' 15 jest dokładniejsza.


Nie, nie ma żadnych generyków w Objective-C, chyba że chcesz używać szablonów C++ w swoich klasach custom collection (co zdecydowanie odradzam).

Objective-C posiada funkcję dynamicznego pisania, co oznacza, że runtime nie dba o typ obiektu, ponieważ wszystkie obiekty mogą odbierać wiadomości. Po dodaniu obiektu do wbudowanej kolekcji są one traktowane tak, jakby były typu id. Ale nie martw się, po prostu wysyłaj wiadomości do tych obiektów jak zwykle; będzie to działać dobrze (o ile oczywiście jeden lub więcej obiektów w kolekcji nie odpowiada na wiadomość, którą wysyłasz) .

Generyki są potrzebne w językach takich jak Java i C#, ponieważ są silnymi, statycznie typowanymi językami. Zupełnie inna gra niż funkcja dynamicznego typowania Objective-C.

 91
Author: Marc W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-08 04:09:35

Nie, ale żeby było jaśniej możesz to skomentować z typem obiektu, który chcesz przechowywać, widziałem to kilka razy, kiedy trzeba coś napisać w Javie 1.4) np.:

NSMutableArray* /*<TypeA>*/ arrayName = ....

Lub

NSDictionary* /*<TypeA, TypeB>*/ dictionaryName = ...
 11
Author: Mark Rhodes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-11-19 23:31:45

Nie ma generyków w Objective-C.

From the Docs

Tablice są uporządkowanymi zbiorami obiektów. Cocoa udostępnia kilka klas tablic, NSArray, NSMutableArray (podklasa NSArray) i NSPointerArray.

 6
Author: Matthew Vines,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-11 15:34:43

Apple dodało generics do ObjC w XCode 7:

@property NSArray<NSDate *>* dates;
- (NSArray<NSDate *> *)datesBeforeDate:(NSDate *)date;
- (void)addDatesParsedFromTimestamps:(NSArray<NSString *> *)timestamps;

Zobacz tutaj: https://developer.apple.com/library/prerelease/mac/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-ID61

 6
Author: user1259710,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-08 22:13:25

To zostało wydane w Xcode 7 (Wreszcie!)

Zauważ, że w kodzie Objective C, jest to tylko sprawdzanie w czasie kompilacji; nie będzie żadnego błędu w czasie wykonywania tylko po umieszczeniu niewłaściwego typu w kolekcji lub przypisaniu do wpisanej właściwości.

Zadeklarować:

@interface FooClass <T> : NSObject
@property (nonatomic) T prop;
@end

Użycie:

FooClass<NSString *> *foo = [[FooClass alloc] init];
NSArray<FooClass<NSString *> *> *fooAry = [NSArray array];

Uważaj na te* s.

 5
Author: Kevin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 16:38:35

Ogólne NSArrays mogą być realizowane przez podklasowanie NSArray i przedefiniowanie wszystkich dostarczonych metod z bardziej restrykcyjnymi. Na przykład,

- (id)objectAtIndex:(NSUInteger)index

Musiałby być przedefiniowany w

@interface NSStringArray : NSArray

Jako

- (NSString *)objectAtIndex:(NSUInteger)index

Aby NSArray zawierał tylko Nsstringi.

Utworzona podklasa może być używana jako zamiennik drop-in i przynosi wiele przydatnych funkcji: ostrzeżenia kompilatora, dostęp do właściwości, lepsze tworzenie kodu i uzupełnianie w Xcode. / Align = "left" / funkcje, nie ma potrzeby redefiniowania rzeczywistej implementacji - metody NSArray nadal mogą być używane.

Można to zautomatyzować i sprowadzić do tylko dwóch wyrażeń, co zbliża go do języków, które obsługują generyki. Stworzyłem automatyzację z WMGenericCollection , gdzie szablony są dostarczane jako makra preprocesora C.

Po zaimportowaniu pliku nagłówkowego zawierającego makro, możesz utworzyć ogólny nsArray z dwoma instrukcjami: jednym dla interfejs i jeden do realizacji. Musisz tylko podać typ danych, który chcesz przechowywać, oraz nazwy podklas. WMGenericCollection udostępnia takie szablony dla NSArray, NSDictionary i NSSet, a także ich zmiennymi odpowiednikami.

Przykład: List<int> może być realizowany przez niestandardową klasę o nazwie NumberArray, która jest tworzona z następującą instrukcją:

WMGENERICARRAY_INTERFACE(NSNumber *, // type of the value class
                         // generated class names
                         NumberArray, MutableNumberArray)

Po utworzeniu NumberArray możesz go używać wszędzie w swoim projekcie. Brakuje w nim składni <int>, ale możesz wybrać własny schemat nazewnictwa, aby oznaczyć je jako klasy jako szablony.

 4
Author: w-m,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-04 22:13:40

Spójrz na:

Https://github.com/tomersh/Objective-C-Generics

Wydaje się być rodzajem generyków biednego człowieka, zmieniając mechanizm sprawdzania protokołu.

 2
Author: David Jeske,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-01 16:47:21

Teraz marzenia się spełniają - są Generyki w Objective-C od dziś (dzięki, WWDC). To nie żart - na oficjalnej stronie Swift:

Nowe funkcje składni pozwalają pisać bardziej ekspresyjny kod przy jednoczesnym zwiększeniu spójności w całym języku. Zestawy SDK wykorzystały nowe funkcje Objective-C, takie jak generics i nullability adnotation, aby Kod Swift był jeszcze czystszy i bezpieczniejszy. Oto tylko próbka ulepszeń Swift 2.0.

I obraz, który potwierdza to: Objective - C generics

 2
Author: htzfun,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-09 14:54:23

Po prostu chcę tu wskoczyć. Napisałem post na blogu tutaj o generykach.

Rzecz, którą chcę wnieść, to to, że Generyki mogą być dodawane do dowolnej klasy , a nie tylko do klas kolekcji, jak wskazuje Apple.

Z powodzeniem dodałem następnie do różnych klas, ponieważ działają dokładnie tak samo, jak Kolekcje Apple. ie. sprawdzanie czasu kompilacji, uzupełnianie kodu, umożliwianie usuwania odlewów itp.

Enjoy.

 2
Author: drekka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-16 12:07:32

Klasy zbiorów dostarczane przez frameworki Apple i GNUStep są pół-generyczne, ponieważ zakładają, że są obiektami, które są sortowalne, a niektóre odpowiadają na określone wiadomości. Dla prymitywów takich jak floats, ints, itp, cała struktura tablic C jest nienaruszona i może być używana, a dla nich są specjalne obiekty wrapper do użycia w klasach kolekcji ogólnych (np. NSNumber). Ponadto Klasa kolekcji może być podklasowana (lub specjalnie modyfikowana za pomocą kategorii) do Akceptuj obiekty dowolnego typu, ale cały kod obsługi typu musisz napisać samodzielnie. Wiadomości mogą być wysyłane do dowolnego obiektu, ale powinny zwracać null, jeśli jest to nieodpowiednie dla obiektu, lub wiadomość powinna zostać przekazana do odpowiedniego obiektu. Błędy typu True powinny być przechwytywane podczas kompilacji, a nie podczas wykonywania. W czasie wykonywania powinny być obsługiwane lub ignorowane. Wreszcie, Objc zapewnia funkcje odbicia w czasie wykonywania do obsługi trudnych przypadków i odpowiedzi na wiadomości, określonego typu i usług mogą być sprawdzanie obiektu przed wysłaniem wiadomości lub umieszczeniem go w niewłaściwej kolekcji. Uważaj, że różne biblioteki i frameworki przyjmują różne konwencje co do tego, jak ich obiekty zachowują się, gdy wysyłane wiadomości nie mają odpowiedzi na kod, więc RTFM. Poza programami zabawkowymi i debugującymi, większość programów nie powinna się zawieszać, chyba że naprawdę nawalają i próbują zapisywać złe dane do pamięci lub dysku, wykonywać nielegalne operacje (np. podzielić przez zero, ale to też można złapać), lub dostęp do zasobów systemu bez ograniczeń. Dynamika i czas działania Objective - C pozwala na to, że rzeczy mogą się nie udać i powinny być wbudowane w twój kod. (HINT) jeśli masz problemy z generycznością w swoich funkcjach, spróbuj trochę specyfiki. Zapisz funkcje z określonymi typami i pozwól runtime select (dlatego nazywane są selektorami!) odpowiedniej funkcji członka w czasie wykonywania.

Example:
    -(id) sort (id) obj;  // too generic. catches all.
     // better
    -(id) sort: (EasilySortableCollection*) esc;
    -(id) sort: (HardToSortCollection*) hsc; 
    ...
    [Sorter  sort: MyEasyColl];
    [Sorter  sort: MyHardColl];
 -2
Author: Chris Reid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-10 23:41:39