2010-01-22 3 views
22

Possible en double:
How does an underscore in front of a variable in a cocoa objective-c class work?iPhone Ivar de convention de nommage

J'ai remarqué que dans un grand nombre de documents de référence là-bas, je vois que beaucoup du temps, des variables sont nommés _variable dans le fichier .h, puis sont @ synthesize'd dans le fichier .m comme

@synthesize variable = _variable; 

Pourquoi est-ce fait? Qu'est-ce que je rate?

Merci!

+0

J'ai vu 'ivar_' être utilisé à la place de' _ivar' aussi, mais je ne peux pas vraiment en faire un argument, sauf qu'ils ont l'air mieux ... –

Répondre

21

Il n'y a pas consensus sur ce. Certaines personnes aiment l'utiliser pour plus de clarté afin de séparer les variables de classe, et comme un autre répondant a noté d'éviter le conflit avec les noms de paramètres entrants. Même dans l'exemple de code Apple, l'utilisation est mixte.

Cependant, je préfère fortement de ne pas utiliser le préfixe _ et ont deux bonnes raisons:

1) Certaines personnes pensent que le _ est un bon indicateur de « privé ». Ma prise est que aucune variable locale de classe devrait être accédée sans un setter/getter (propriété) et ainsi ils sont TOUS privés - étant donné que pourquoi ne pas les nommer d'une manière plus facile à lire et à utiliser la saisie semi-automatique?Tout chevauchement dans les noms des paramètres est rapidement révélé par le compilateur, et évité grâce à une dénomination plus réfléchie des paramètres (ou des variables internes). 2) (raison encore meilleure) - si vous utilisez "refactor" dans XCode sur une classe interne var nommée comme la propriété utilisée pour y accéder, la propriété et l'instruction synthesize seront également renommées. Si vous utilisez refactor sur une variable de classe préfixée par un _, le nom de la propriété ne sera pas modifié - juste le mappage de synthésize au nom interne. Je ne veux presque jamais que le nom varie de la propriété à la variable réelle à laquelle il expose l'accès. Cela seul fait que je ne veux jamais utiliser _ comme préfixe de variable, puisque pouvoir changer de nom est à peu près la chose la plus utile que vous pouvez faire pour améliorer la clarté du code.

+0

Toutes les suggestions sur les paramètres de méthode de nommage afin qu'ils ne soient pas conflit avec les noms ivar? Ceci est particulièrement important pour initWith * ou les setters de propriétés implémentés manuellement. J'ai essayé les préfixes "a/an" et "new" pendant un certain temps, mais ce n'est pas toujours pratique (comme quand un nom est au pluriel). J'ai également essayé les préfixes de soulignement pour les paramètres, mais il est facile de rendre fou les lecteurs de code en raison des préférences d'Apple et de la communauté de développeurs pour utiliser le soulignement avec les ivars. Dans une certaine mesure, cela s'applique également au suffixe underscore. – aleh

+0

Ces jours-ci j'utilise les préfixes "\ _" pour toutes les classes internes (en face je sais!) Parce que je les utilise uniquement avec des propriétés - et comme les propriétés créent automatiquement des iVars avec _ comme préfixe je m'en tiens à ça. Refactor fonctionne sur les propriétés, et avec les propriétés, vous ne voyez jamais le nom, donc le "\ _" n'a pas vraiment d'importance. Cela élimine également le problème de chevauchement que vous avez. Je vais modifier cette réponse pour refléter ma nouvelle pensée à un moment donné. –

+0

Je vois. Je suis toujours personnellement hésitant à accéder à mes propres ivars via des propriétés bien (par exemple plus comme _ivar/ivar vs self.ivar): n'aime pas que les propriétés publiques accessibles en écriture ou la redéclaration des propriétés en lecture seule soient modifiables en .m. Mais comme vous l'avez dit, il n'y a pas de consensus :) – aleh

1

Ceci est purement conventionnel. Je suppose que sa commune parce que quand vous faites un appel getter méthode comme ceci:

[myObject variable] 

vous appellent en fait une méthode, pas accéder directement à une variable. le _ devant indique clairement que vous parlez d'une variable. Personnellement, je trouve cette syntaxe agaçante et distrayante. Je trouve cela inutile, mais vous avez raison, cela apparaît ici et là.

4

Parfois, les gens utilisent mVarName (C++) et en Obj-c le style semble être _varName. Un problème que vous pouvez avoir, imaginez que votre argument à une fonction est ... set: (int) x - MAIS - vous avez un iVar appelé x ... bien votre va faire pleurer le compilateur sur des trucs comme ça - pour ne pas mentionner sa confusion.

Le m, _, tout ce qui aide à montrer quelles sont les propriétés membres de la classe.

-(void) set:(int)x 
{ 
x = x; // x is an ivar! heh 
} 

VS

-(void) set:(int)x 
{ 
_x = x; // ahh I see! 
} 
15

En utilisant cette syntaxe est une option pour le rendre plus clair que la Ivar et la propriété sont des choses différentes.

Pour coder externe à la classe, il n'y a aucune différence car il utilise la propriété.

Pour le code dans l'implémentation de la classe elle-même, cela peut le rendre plus clair lorsque l'ivar est utilisé par rapport à la propriété.

Par exemple, disons que nous avons une Ivar/propriété pour un objet NSNumber:

@interface MyClass : NSObject { 
    NSNumber *num; 
} 
@property (nonatomic, retain) NSNumber *num; 
- (void)doSomething; 
@end 

@implementation MyClass 
@synthesize num; 

- (void)doSomething { 
    // set the property, num is properly retained 
    self.num = [NSNumber numberWithInteger:1]; 

    // accidentally set the ivar, num is NOT retained 
    num = [NSNumber numberWithInteger:2]; 
} 
@end 

et en utilisant maintenant un nom différent pour le Ivar et la propriété:

@interface MyClass : NSObject { 
    NSNumber *i_num; 
} 
@property (nonatomic, retain) NSNumber *num; 
- (void)doSomething; 
@end 

@implementation MyClass 
@synthesize num = i_num; 

- (void)doSomething { 
    // set the property, num is properly retained 
    self.num = [NSNumber numberWithInteger:1]; 

    // compiler error, there is no ivar named "num" 
    num = [NSNumber numberWithInteger:2]; 

    // set the ivar, so it needs to be a retained object 
    i_num = [[NSNumber alloc] initWithInteger:3]; 
} 
@end 
1

Je préfère ne pas utiliser le préfixe '_' car Apple l'utilise régulièrement. En évitant le préfixe, j'ai alors une plus grande confiance que mes ivars ne se heurtent pas à Apple quand j'étends une classe tactile de cacao. Puisque nous n'avons pas accès à la source de la classe de base, c'est vraiment la seule façon que je connaisse pour éviter la réutilisation accidentelle d'ivars privés existants.

Tout comme

noms de méthode commençant par « _ », un seul caractère underscore, sont réservés pour une utilisation par Apple.

9

Les réponses précédentes manquent l'histoire derrière cela. Avant Objective-C 2.0, il n'y avait pas de propriétés. Donc, vous auriez un objet avec des variables d'instance comme celle-ci:

@interface MyObject: NSObject { 
    NSArray *myArray; 
} 

@end 

Mais comment voulez-vous y accéder à partir d'autres objets? la solution était de faire des setters et des getters. Mais pour éviter toute confusion, ils le feraient comme ceci:

@interface MyObject: NSObject { 
    NSArray *_myArray; 
} 

- (NSArray *)myArray; 
- (void)setMyArray:(NSArray *)myArray; 

@end 

Le _ sert à dissiper la confusion entre l'instance et la variable _myArray la méthode -myArray.

+0

Je ne suis pas sûr de savoir comment garder le nom ivar sans un underscore serait confondu avec le nom de la méthode myArray. Pas par le compilateur au moins. Appeler une méthode [obj myArray] ou se référer à son sélecteur @selector (myArray) était toujours différent de faire référence à son ivar (obj-> myArray ou simplement myArray ou self-> myArray de ses propres méthodes). – aleh

+0

C'est plus pour quand vous êtes dans une méthode d'instance d'une classe. Il est facile d'écrire accidentellement 'myArray = @ [@" A ", @" B ", @" C "];' au lieu de 'myArray = @ [@" A ", @" B ", @" C "]; '. –

+0

OK, je comprends. Je suppose que vous vouliez dire qu'il est plus facile de fausser 'myArray = ...' en signifiant 'self.myArray = ...'. – aleh

0

Ma préférence, après Google, est tout simplement d'ajouter un trait de soulignement et synthétiser explicitement (même si je suis réimplémentant):

@synthesize varName=varName_; 

Si je vois que l'extérieur de fuite en évidence init..., dealloc ou un accesseur, Je sais que quelque chose est louche.

Questions connexes