95 votes

Est-il possible d’appliquer la dactylographie sur NSArray, NSMutableArray, etc.. ?

Puis-je faire un NSMutableArray où tous les éléments sont de type SomeClass ?

53voto

Barry Wark Points 73462

Ce qui est relativement commun de question pour les personnes en transition de fortement du type de langages (comme C++ ou Java) de plus en plus faiblement ou typées dynamiquement des langages comme Python, Ruby, ou Objective-C Objective-C, la plupart des objets héritent de NSObject (type id) (le reste hériter d'une autre classe racine comme NSProxy et peut également être de type id), et un message peut être envoyé à n'importe quel objet. Bien sûr, l'envoi d'un message à une instance qu'il ne reconnaît pas peut provoquer une erreur d'exécution (et aussi à cause d'un compilateur d'avertissement appropriés -W drapeaux). Tant qu'une instance répond au message que vous envoyez, vous ne se soucient pas quelle classe il appartient. Ceci est souvent appelé "duck typing" car "s'il charlatans comme un canard [c'est à dire qui répond à un sélecteur], c'est un canard [c'est à dire qu'il peut gérer le message; qui se soucie de ce que la classe qu'il est]".

Vous pouvez tester si une instance répond à un sélecteur au moment de l'exécution avec l' -(BOOL)respondsToSelector:(SEL)selector méthode. En supposant que vous voulez l'appeler une méthode sur tous les cas dans un tableau mais ne sont pas sûr que toutes les instances peuvent gérer le message (vous ne pouvez pas utiliser NSArrays' -[NSArray makeObjectsPerformSelector:], quelque chose de ce genre:

for(id o in myArray) {
  if([o respondsToSelector:@selector(myMethod)]) {
    [o myMethod];
  }
}

Si vous contrôlez le code source pour les instances à mettre en œuvre la ou les méthode(s) que vous souhaitez appeler, l'approche plus commune serait de définir un @protocol qui contient ces méthodes et de déclarer que les classes en question, de mettre en œuvre ce protocole dans leur déclaration. Dans cette utilisation, @protocol est analogue à une Interface Java ou en C++ une classe de base abstraite. Vous pouvez ensuite tester la conformité de l'ensemble du protocole plutôt que de répondre à chaque méthode. Dans l'exemple précédent, il ne fera pas beaucoup de différence, mais si vous étiez en appelant plusieurs méthodes, il pourrait simplifier les choses. L'exemple serait alors:

for(id o in myArray) {
  if([o conformsToProtocol:@protocol(MyProtocol)]) {
    [o myMethod];
  }
}

en supposant MyProtocol déclare myMethod. Cette seconde approche est favorisée, car elle précise l'intention du code plus que le premier.

Souvent, l'une de ces approches vous libère de s'inquiéter de savoir si tous les objets dans un tableau sont d'un type donné. Si vous n'avez toujours des soins, la dynamique de la langue est l'approche de test unitaire, test unitaire, test d'unité. En raison d'une régression dans cette exigence de produire un (probablement irrécupérable) runtime (pas le temps de compilation) erreur, vous avez besoin de la couverture de test pour vérifier le comportement de sorte que vous ne relâchez pas un coup retentissant dans la nature. Dans ce cas, d'effectuer une opération qui modifie le tableau, puis vérifiez que toutes les instances dans le tableau appartiennent à une classe donnée. Avec une bonne couverture de test, vous n'avez même pas besoin de l'ajout gestion d'exécution de la vérification de l'instance de l'identité. Vous avez une bonne couverture de tests unitaires, n'est-ce pas?

36voto

Chuck Points 138930

Vous pourriez faire une catégorie avec un -addSomeClass: méthode pour permettre la compilation statique type de vérification (de sorte que le compilateur pourrait vous permettre de savoir si vous essayez d'ajouter un objet qu'il connaît, c'est une autre classe par le biais de la méthode), mais il n'y a pas de véritable moyen de faire valoir un tableau ne contient que des objets d'une classe donnée.

En général, il ne semble pas être une nécessité pour une telle contrainte en Objective-C. je ne pense pas que j'ai jamais entendu une expérience de Cacao programmeur souhaite pour cette fonction. Les seules personnes qui semblent sont les programmeurs à partir d'autres langues qui sont encore à penser dans ces langues. Si vous ne souhaitez que des objets d'une classe donnée dans un tableau, seulement coller des objets de cette classe là. Si vous voulez tester votre code fonctionne correctement, le tester.

11voto

bendytree Points 2684

Vous pourriez sous-classe NSMutableArray d'appliquer le type de sécurité.

NSMutableArray est une classe de cluster, sorte de sous-classement n'est pas trivial. J'ai fini par hériter de NSArray et transmis les invocations d'un tableau à l'intérieur de cette classe. Le résultat est une classe appelée ConcreteMutableArray qui est facile à la sous-classe. Voici ce que j'ai trouvé:

Mise à jour: la caisse de ce billet de blog de Mike Cendres sur sous-classement d'une classe de cluster.

Inclure ces fichiers dans votre projet, puis de générer tous les types que vous le souhaitez à l'aide de macros:

MyArrayTypes.h

CUSTOM_ARRAY_INTERFACE(NSString)
CUSTOM_ARRAY_INTERFACE(User)

MyArrayTypes.m

CUSTOM_ARRAY_IMPLEMENTATION(NSString)
CUSTOM_ARRAY_IMPLEMENTATION(User)

Utilisation:

NSStringArray* strings = [NSStringArray array];
[strings add:@"Hello"];
NSString* str = [strings get:0];

[strings add:[User new]];  //compiler error
User* user = [strings get:0];  //compiler error

D'Autres Pensées

  • Il hérite d' NSArray à l'appui de la sérialisation/désérialisation
  • Selon votre goût, vous souhaiterez peut-être modifier/masquer les méthodes génériques comme

    - (void) addObject:(id)anObject

7voto

Barry Wark Points 73462

Jetez un oeil à https://github.com/tomersh/Objective-C-Generics, une implémentation de compilation (implémenté preprocessor) génériques pour Objective-C. Ce blog a un bel aperçu. Fondamentalement, vous obtenez compilation vérification (avertissements ou erreurs), mais aucune pénalité de runtime pour les médicaments génériques.

4voto

NSAddict Points 2579

Ce projet Github implémente exactement cette fonctionnalité.

Vous pouvez ensuite utiliser les `` entre crochets, comme vous le feriez en c#.

De leurs exemples :

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X