Je viens de commencer à programmer Objective-C et, ayant une formation en Java, je me demande comment les gens qui écrivent des programmes Objective-C traitent des méthodes privées.
Je comprends qu'il peut y avoir plusieurs conventions et habitudes et je considère cette question comme un agrégateur des meilleures techniques que les gens utilisent pour traiter les méthodes privées dans Objective-C.
Veuillez inclure un argument pour votre approche lors de sa publication. Pourquoi est-il bon? Quels sont ses inconvénients (à votre connaissance) et comment les traitez-vous?
Quant à mes conclusions jusqu'à présent.
Il est possible d'utiliser des catégories [par exemple MyClass (Private)] définies dans le fichier MyClass.m pour regrouper des méthodes privées.
Cette approche comporte 2 problèmes:
- Xcode (et le compilateur?) Ne vérifie pas si vous définissez toutes les méthodes dans la catégorie privée dans le bloc @implementation correspondant
- Vous devez mettre @interface déclarant votre catégorie privée au début du fichier MyClass.m, sinon Xcode se plaint d'un message comme "self peut ne pas répondre au message" privateFoo ".
Le premier problème peut être contourné avec une catégorie vide [par exemple MyClass ()].
Le second me dérange beaucoup. J'aimerais voir des méthodes privées implémentées (et définies) vers la fin du fichier; Je ne sais pas si c'est possible.
la source
Réponses:
Il n'y a pas, comme d'autres l'ont déjà dit, de méthode privée dans Objective-C. Cependant, à partir d'Objective-C 2.0 (c'est-à-dire Mac OS X Leopard, iPhone OS 2.0 et versions ultérieures), vous pouvez créer une catégorie avec un nom vide (c'est-à-dire
@interface MyClass ()
) appelé Extension de classe . Ce qui est unique dans une extension de classe, c'est que les implémentations de méthodes doivent aller de la même manière@implementation MyClass
que les méthodes publiques. Je structure donc mes cours comme ceci:Dans le fichier .h:
Et dans le fichier .m:
Je pense que le plus grand avantage de cette approche est qu'elle vous permet de regrouper vos implémentations de méthode par fonctionnalité, et non par la distinction (parfois arbitraire) public / privé.
la source
if (bSizeDifference && [self isSizeDifferenceSignificant:fWidthCombined])...
j'imbrique un appel comme celui-ci: Ensuite, fWidthCombined était toujours à 0.Il n'y a pas vraiment de "méthode privée" dans Objective-C, si le runtime peut déterminer quelle implémentation utiliser il le fera. Mais cela ne veut pas dire qu'il n'y a pas de méthodes qui ne font pas partie de l'interface documentée. Pour ces méthodes, je pense qu'une catégorie est très bien. Plutôt que de placer le
@interface
en haut du fichier .m comme votre point 2, je le mettrais dans son propre fichier .h. Une convention que je suis (et j'ai vu ailleurs, je pense que c'est une convention Apple car Xcode le prend désormais automatiquement en charge) consiste à nommer un tel fichier d'après sa classe et sa catégorie avec un + les séparant, donc@interface GLObject (PrivateMethods)
on peut le trouver dansGLObject+PrivateMethods.h
. La raison de fournir le fichier d'en-tête est que vous puissiez l'importer dans vos classes de tests unitaires :-).Soit dit en passant, en ce qui concerne l'implémentation / définition des méthodes vers la fin du fichier .m, vous pouvez le faire avec une catégorie en implémentant la catégorie au bas du fichier .m:
ou avec une extension de classe (ce que vous appelez une "catégorie vide"), définissez simplement ces méthodes en dernier. Les méthodes Objective-C peuvent être définies et utilisées dans n'importe quel ordre dans l'implémentation, donc rien ne vous empêche de mettre les méthodes "privées" à la fin du fichier.
Même avec des extensions de classe, je vais souvent créer un en-tête séparé (
GLObject+Extension.h
) afin que je puisse utiliser ces méthodes si nécessaire, imitant la visibilité "ami" ou "protégé".Depuis que cette réponse a été écrite à l'origine, le compilateur clang a commencé à faire deux passes pour les méthodes Objective-C. Cela signifie que vous pouvez éviter de déclarer complètement vos méthodes "privées" et qu'elles soient au-dessus ou en dessous du site appelant, elles seront trouvées par le compilateur.
la source
Bien que je ne sois pas un expert Objective-C, je ne définis personnellement que la méthode dans l'implémentation de ma classe. Certes, il doit être défini avant (ci-dessus) toutes les méthodes qui l'appellent, mais cela prend certainement le moins de travail à faire.
la source
La définition de vos méthodes privées dans le
@implementation
bloc est idéale dans la plupart des cas. Clang les verra dans@implementation
, indépendamment de l'ordre de déclaration. Il n'est pas nécessaire de les déclarer dans une continuation de classe (aka extension de classe) ou une catégorie nommée.Dans certains cas, vous devrez déclarer la méthode dans la continuation de classe (par exemple si vous utilisez le sélecteur entre la continuation de classe et le
@implementation
).static
les fonctions sont très bonnes pour les méthodes privées particulièrement sensibles ou sensibles à la vitesse.Une convention pour nommer les préfixes peut vous aider à éviter d'écraser accidentellement les méthodes privées (je trouve le nom de classe comme un préfixe sûr).
Les catégories nommées (par exemple
@interface MONObject (PrivateStuff)
) ne sont pas une bonne idée en raison des collisions de noms potentielles lors du chargement. Ils ne sont vraiment utiles que pour les méthodes amis ou protégées (qui sont très rarement un bon choix). Pour vous assurer d'être averti des implémentations de catégorie incomplètes, vous devez réellement l'implémenter:Voici un petit aide-mémoire annoté:
MONObject.h
MONObject.m
Une autre approche qui peut ne pas être évidente: un type C ++ peut être à la fois très rapide et fournir un degré de contrôle beaucoup plus élevé, tout en minimisant le nombre de méthodes objc exportées et chargées.
la source
Vous pouvez essayer de définir une fonction statique au-dessous ou au-dessus de votre implémentation qui prend un pointeur vers votre instance. Il pourra accéder à n'importe laquelle de vos variables d'instances.
la source
Vous pourriez utiliser des blocs?
Je sais que c'est une vieille question, mais c'est l'une des premières que j'ai trouvées lorsque je cherchais une réponse à cette question. Je n'ai vu cette solution discutée nulle part ailleurs, alors faites-moi savoir s'il y a quelque chose de stupide à faire cela.
la source
static
). Mais j'ai expérimenté l'attribution de blocs aux ivars privés (à partir de la méthode init) - un peu à la manière de JavaScript - qui permet également d'accéder aux ivars privés, ce qui n'est pas possible à partir des fonctions statiques. Pas encore sûr de ce que je préfère.tous les objets dans Objective C sont conformes au protocole NSObject, qui conserve la méthode performSelector : . Je cherchais également auparavant un moyen de créer des méthodes "auxiliaires ou privées" que je n'avais pas besoin d'exposer au niveau public. Si vous souhaitez créer une méthode privée sans surcharge et sans avoir à la définir dans votre fichier d'en-tête, essayez ceci ...
définir votre méthode avec une signature similaire à celle du code ci-dessous ...
puis quand vous avez besoin de référencer la méthode, appelez-la simplement comme sélecteur ...
cette ligne de code invoquera la méthode que vous avez créée et n'aura pas d'avertissement gênant de ne pas l'avoir définie dans le fichier d'en-tête.
la source
Si vous vouliez éviter le
@interface
blocage en haut, vous pouviez toujours mettre les déclarations privées dans un autre fichier, ce quiMyClassPrivate.h
n'était pas idéal, mais cela n'encombrait pas l'implémentation.MyClass.h
MyClassPrivate.h
MyClass.m
la source
Une autre chose que je n'ai pas vue mentionnée ici - Xcode prend en charge les fichiers .h avec "_private" dans le nom. Disons que vous avez une classe MyClass - vous avez MyClass.m et MyClass.h et maintenant vous pouvez également avoir MyClass_private.h. Xcode reconnaîtra cela et l'inclura dans la liste des "homologues" dans l'éditeur adjoint.
la source
Il n'y a aucun moyen de contourner le problème # 2. C'est juste la façon dont le compilateur C (et donc le compilateur Objective-C) fonctionne. Si vous utilisez l'éditeur XCode, la fenêtre contextuelle de la fonction devrait faciliter la navigation dans les blocs
@interface
et@implementation
dans le fichier.la source
Il y a un avantage à l'absence de méthodes privées. Vous pouvez déplacer la logique que vous aviez l'intention de masquer dans la classe distincte et l'utiliser comme délégué. Dans ce cas, vous pouvez marquer l'objet délégué comme privé et il ne sera pas visible de l'extérieur. Déplacer la logique vers une classe séparée (peut-être plusieurs) améliore la conception de votre projet. Parce que vos classes deviennent plus simples et vos méthodes sont regroupées en classes avec des noms propres.
la source
Comme d'autres l'ont dit, la définition de méthodes privées dans le
@implementation
bloc est OK dans la plupart des cas.Sur le sujet de l' organisation du code - j'aime les garder ensemble
pragma mark private
pour une navigation plus facile dans Xcodela source