Variables d’instance déclarées dans le fichier d’implémentation ObjC

Je regardais la vidéo d’introduction de l’ARC WWDC et j’ai vu quelque chose que je n’avais jamais vu auparavant dans ObjC quand un ingénieur Apple a parlé d’un exemple de Stack.

Le code suivant a été utilisé pour un exemple de stack avec ARC:

@implementation Stack { // instance variable declared in implementation context NSMutableArray *_array; } - (id)init { if (self = [super init]) _array = [NSMutableArray array]; return self; } - (void)push:(id)x { [_array addObject:x]; } - (id)pop { id x = [_array lastObject]; [_array removeLastObject]; return x; } @end 

Notez la variable d’instance déclarée juste après la directive @implementation .

Maintenant, la chose qui m’a surpris, c’est qu’une variable d’instance pourrait effectivement être déclarée dans le fichier d’implémentation, sans qu’il s’agisse d’une variable statique. Mes questions seraient les suivantes:

  • Est-ce une nouvelle construction introduite dans le SDK pour iOS 5 ou est-ce possible depuis longtemps?
  • Serait-ce une bonne pratique de déclarer des variables d’instance dans l’implémentation, si les variables d’instance ne sont pas accessibles en dehors de l’object? Cela semble beaucoup plus propre que l’utilisation de la directive @private.

C’est en effet une nouvelle fonctionnalité de langage, et si vous devez déclarer vos ivars (plutôt que de simplement déclarer des propriétés et laisser le compilateur générer des ivars pour vous), c’est une bonne pratique. Vos fichiers d’en-tête en théorie ne devraient exposer que l’interface publique de vos classes; tout le rest appartient à la mise en œuvre.

Une mise en garde est que les ivars de fichiers d’implémentation ne sont pas visibles pour les sous-classes, ce qui peut parfois être un peu gênant si vous avez généré manuellement des installeurs et des getters que vous devez sous-classer.

Déclarer iVars dans l’implémentation est définitivement une nouvelle construction dans l’objective C. Vous devez utiliser xcode4.2 et avoir le compilateur LLVM sélectionné dans vos parameters de construction. L’idée est de garder vos fichiers d’en-tête plus propres. Vous pouvez lister vos ivars entre accolades comme cet exemple;

 @implementation MyClass { int var1; int var2; } 

La réponse donnée par Rahul n’est pas vraiment correcte, bien que vous puissiez supprimer les variables de la manière dont il dit qu’elles seraient statiques par le compilateur. Probablement pour les cas où il les utilisait, cela n’avait pas d’importance.

Je suis nouveau à l’Objectif C et j’ai trouvé très étrange la pratique consistant à déclarer des ivars dans l’en-tête. Cela signifie déclarer l’état interne d’un object dans son en-tête public, ce qui défie le concept d’encapsulation.

Par exemple, disons que vous possédez un iPad. Apple ne veut pas que vous cassiez l’iPad et que vous le déchaîniez, et que vous vous amusiez avec les éléments à l’intérieur. S’ils veulent que vous modifiiez quelque chose, l’IPad aura un paramètre qui vous permettra de changer cela.

De même, je ne veux pas que les autres programmeurs voient les ivars de mes objects. C’est l’état interne de mon object. Si je veux que vous accédiez à l’état interne, je déclarerai ses propriétés.

Donc, comme dans les autres langues, je cacherais mes ivars dans le fichier d’implémentation et ne les déclarais pas dans l’en-tête.

La déclaration d’ivars dans l’en-tête me semble très étrange. Ces ivars sont spécifiques à l’implémentation et ne devraient tout simplement pas faire partie du fichier d’en-tête.