361 votes

Meilleure façon de définir des méthodes privées pour une classe en Objective-C

Je viens de commencer la programmation en Objective-C et, ayant un arrière-plan en Java, me demande comment les gens de l'écriture Objective-C programmes traitent des méthodes privées.

Je comprends, il peut y avoir plusieurs conventions et habitudes et de réfléchir à cette question comme un agrégateur de les meilleures techniques d'utilisation de personnes traitant avec les méthodes privées en Objective-C.

Veuillez inclure un argument pour votre approche lors de la publication. Pourquoi est-il bon? Qui les inconvénients-t-il (que vous connaissez) et comment vous devez traiter avec eux?


Comme pour mes résultats jusqu'à présent.

Il est possible d'utiliser les catégories [par exemple: Maclasse (Privé)] définie dans Maclasse.m fichier de groupe de méthodes privées.

Cette approche a 2 problèmes:

  1. Xcode (et le compilateur?) ne pas cocher si vous définir toutes les méthodes, en privé, de la catégorie correspondante @mise en œuvre de bloc
  2. Vous devez mettre @interface de déclarer votre catégorie dans le début de MyClass.m fichier, sinon Xcode se plaint avec un message comme "auto peut ne pas répondre à un message "privateFoo".

Le premier problème peut être contourné avec une catégorie vide [par exemple: Maclasse ()].
Le second qui me dérange beaucoup. J'aimerais voir privé, les méthodes de mise en œuvre (et définie), à proximité de la fin du fichier, je ne sais pas si c'est possible.

438voto

Alex Points 19842

Il n'y a pas, comme d'autres l'ont déjà dit, une telle chose comme une méthode privée en Objective-C. Toutefois, en Objective-C 2.0 (sens de Mac OS X Leopard, iPhone OS 2.0, et plus tard), vous pouvez créer une catégorie avec un nom vide (c - @interface MyClass ()) a appelé Extension de Classe. Ce qui est unique au sujet d'une extension de classe, c'est que la méthode implémentations doivent aller dans le même @implementation MyClass que les méthodes publiques. Donc, je structure mes classes comme ceci:

Dans l' .h fichier:

@interface MyClass {
    // My Instance Variables
}

- (void)myPublicMethod;

@end

Et dans la .m fichier:

@interface MyClass()

- (void)myPrivateMethod;

@end

@implementation MyClass

- (void)myPublicMethod {
    // Implementation goes here
}

- (void)myPrivateMethod {
    // Implementation goes here
}

@end

Je pense que le plus grand avantage de cette approche est qu'il vous permet de regrouper votre méthode de mise en œuvre grâce à la fonctionnalité, et non pas par la (parfois arbitraire) distinction public/privé.

37voto

Andy Points 15910

Bien que je ne sois pas un expert en Objective-C, je définis personnellement la méthode dans la mise en œuvre de ma classe. Certes, il doit être défini avant (au-dessus) des méthodes qui l'appellent, mais il prend certainement le moins de travail à faire.

23voto

justin Points 72871

La définition de vos méthodes privées en @implementation bloc est idéal pour la plupart des besoins. Clang va voir à l'intérieur de la @implementation, indépendamment de leur ordre de déclaration. Il n'est pas nécessaire de les déclarer dans une classe de continuation (aka extension de classe) ou le nom de la catégorie.

Dans certains cas, vous aurez besoin de déclarer la méthode dans la classe de poursuite (par exemple, si vous utilisez le sélecteur entre la classe de la poursuite et de l' @implementation).

static fonctions sont très bon pour la particulièrement sensibles ou de la vitesse critique des méthodes privées.

Une convention pour nommer les préfixes peuvent vous aider à éviter accidentellement prépondérant méthodes (je trouve le nom de la classe comme un préfixe de sécurité).

Nommé catégories (par exemple, @interface MONObject (PrivateStuff)) ne sont pas une très bonne idée à cause des conflits de noms lors du chargement. Ils sont vraiment utile pour un ami ou protégés des méthodes (qui sont très rarement un bon choix). Pour vous assurer que vous êtes averti du caractère incomplet de la catégorie des implémentations, en fait, vous devez la mettre en œuvre:

@implementation MONObject (PrivateStuff)
...HERE...
@end

Voici un petit annoté feuille de triche:

MONObject.h

@interface MONObject : NSObject

// public declaration required for clients' visibility/use.
@property (nonatomic, assign, readwrite) bool publicBool;

// public declaration required for clients' visibility/use.
- (void)publicMethod;

@end

MONObject.m

@interface MONObject ()
@property (nonatomic, assign, readwrite) bool privateBool;

// you can use a convention where the class name prefix is reserved
// for private methods this can reduce accidental overriding:
- (void)MONObject_privateMethod;

@end

// The potentially good thing about functions is that they are truly
// inaccessible; They may not be overridden, accidentally used,
// looked up via the objc runtime, and will often be eliminated from
// backtraces. Unlike methods, they can also be inlined. If unused
// (e.g. diagnostic omitted in release) or every use is inlined,
// they may be removed from the binary:
static void PrivateMethod(MONObject * pObject) {
    pObject.privateBool = true;
}

@implementation MONObject
{
    bool anIvar;
}

static void AnotherPrivateMethod(MONObject * pObject) {
    if (0 == pObject) {
        assert(0 && "invalid parameter");
        return;
    }

    // if declared in the @implementation scope, you *could* access the
    // private ivars directly (although you should rarely do this):
    pObject->anIvar = true;
}

- (void)publicMethod
{
    // declared below -- but clang can see its declaration in this
    // translation:
    [self privateMethod];
}

// no declaration required.
- (void)privateMethod
{
}

- (void)MONObject_privateMethod
{
}

@end

Une autre approche qui ne peut pas être évident: d'un C++, peut être à la fois très rapide et fournir un degré beaucoup plus élevé de contrôle, tout en minimisant le nombre de exportés et chargé objc méthodes.

14voto

dreamlax Points 47152

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.

 //.h file
@interface MyClass : Object
{
    int test;
}
- (void) someMethod: anArg;

@end


//.m file    
@implementation MyClass

static void somePrivateMethod (MyClass *myClass, id anArg)
{
    fprintf (stderr, "MyClass (%d) was passed %p", myClass->test, anArg);
}


- (void) someMethod: (id) anArg
{
    somePrivateMethod (self, anArg);
}

@end
 

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