Comment faire une vraie variable d'instance privée?

je veux faire une variable d'instance qui ne peut pas être accessible de l'extérieur. Est-ce que quelque chose comme ça est possible dans l'objectif-c? Je me souviens Qu'Apple a des variables privées et des trucs comme ça, mais si les gens les connaissent, ils peuvent les utiliser. Apple appelle cela "API privée", mais évidemment d'autres peuvent accéder à ce genre de choses s'ils découvrent ce qu'il y a là-dedans.

Jusqu'à présent j'ai cru que quelque chose comme ceci crée une variable d'instance privée:

@interface MyClass : NSObject {
    CGFloat weight;
}

Pas @bien, pas de @synthétiser, juste la déclaration ci-dessus.

Je sais aussi Qu'Apple ajoute un _infrontde leurprivateinstancevariables, mais ils ont dit quelque part qu'ils n'aiment pas voir les autres faire cela parce qu'ils pourraient outrepasser accidentellement les variables d'instance cachées en faisant cela.

Quel est le truc?

51
demandé sur Quinn Taylor 2009-08-11 23:40:08

7 réponses

vous pouvez utiliser le mot-clé @private à l'intérieur du {} pour rendre toutes les déclarations variables ultérieures privées. La visibilité par défaut est @protected (qui est similaire à protected en Java) et cela fonctionne généralement bien. Vous devez déclarer spécifiquement une variable comme @public pour qu'elle soit directement accessible en dehors de la classe.

cette documentation Apple contient plus de détails sur la portée et la visibilité variables.

il y a aussi une différence entre" API privée " et les variables privées. Dans Objective-C, vous ne pouvez pas rendre les méthodes privées - n'importe qui peut appeler n'importe quelle méthode. Il y a plusieurs façons de créer des méthodes "secrètes", mais c'est un peu hors de la portée de cette question. Voici quelques questions relatives à SO:

en ce qui concerne le premier _ devant les variables, sachez Qu'Apple réserve également ce préfixe pour les méthodes" privées". La meilleure façon de vous garantir d'éviter les problèmes est d'utiliser normal conventions de nommage pour vos propres variables et méthodes. Cependant, à moins que vous ne classiez quelque chose de Cocoa (autre que NSObject) vous pouvez être assez confiant que vous ne rencontrerez pas de problèmes.

60
répondu Quinn Taylor 2017-05-23 12:02:12

avec le nouveau compilateur LLVM disponible dans XCode 4 et plus tard, vous pouvez déclarer @private variables dans les catégories par défaut à l'intérieur de votre implémentation (.m) fichier:

@interface ClassName()
{
@private
// private variables here
}
@end

@implementation ClassName
// you can use private variables here
@end

je trouve cela pratique, car je déteste les variables privées de pollution apportent dans mes fichiers d'en-tête.

31
répondu Johannes Rudolph 2012-04-30 14:56:10

vous pouvez définir des méthodes privées en les ayant seulement dans l'implémentation@, et pas dans l'interface@.

de même, vous pouvez définir des variables d'instance privée à l'intérieur d'un bloc anonyme au début de l'implémentation @ - comme vous le faites pour les ivars publics à l'intérieur de l'interface@.

Voir l'exemple suivant.

@interface EXClass : NSObject
{
uint8_t publicInteger;
float publicFloat;
}

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}

rappelez-vous que les méthodes objective-C sont envoyées sous forme de messages à l'exécution, bien que (plutôt que C++'s compiler time binding), donc respondsToSelector: retournerait toujours true et performSelector: appellerait toujours la méthode. Les ivars seraient entièrement privés.

si vous faisiez une bibliothèque, cependant, théoriquement personne ne connaîtrait les méthodes que vous n'avez pas déclarées dans les fichiers d'en-tête.

9
répondu stef 2012-08-19 19:27:43

tous les iVars D'Objectif-C sont protégés par défaut. Si vous n'écrivez pas les méthodes accessor, les autres classes ne pourront pas voir les variables.

Les deux exceptions sont les catégories et les sous-classes.

3
répondu kubi 2009-08-11 19:45:39

Les Docs Apple pour nommer les variables d'instance ne mettent pas explicitement en garde contre l'utilisation de underscore dans le nom des variables d'instance comme le font les documents de la méthode privée.

Nommage des Variables d'Instance et des Types de Données

je me souviens aussi d'une conversation entre WIL Shipley et quelques autres développeurs OS X concernant les underscores. En raison de la façon dont le compilateur Obj-C fonctionne, si Apple devait ajouter une nouvelle variable d'instance pour une classe dans leurs cadres, il causerait toutes les applications utilisant ces cadres à avoir besoin d'être recompilé. En ce qui concerne les variables d'instance préexistantes, vous devriez recevoir un avertissement lorsque vous marchez sur l'une d'elles.

2
répondu criscokid 2011-07-21 23:58:40

j'ai vu l'usage suivant dans une application d'échantillon (PaintGL) par Apple

In .m fichier

@interface MyClass (private)
  - (void) privateMethod();
  @property(...) myProperty;
@end

Disclaimer: l'application d'échantillon a seulement des déclarations de méthode, j'ai vu la déclaration de propriété privée dans ce fil de SO

2
répondu Ege Akpinar 2017-05-23 12:09:37

Vous pouvez pas faire une réelle privé variable d'instance. L'objectif-C est un langage dynamique et il est donc possible d'accéder à n'importe quelle variable (même @private).

Ma meilleure approche:

utilisez-le dans votre bloc d'implémentation .m de fichier. Alors il n'est pas visible et bloque KVC, de sorte que KVC ne fonctionnera pas

@implementation ClassName {
    // default to @protected
    // but the subclasses can't see ivars created in the implementation block
    float number;
}

+ (BOOL)accessInstanceVariablesDirectly {
    return NO; // no KVC
}

@end
1
répondu Binarian 2014-01-03 13:14:47