2009-06-08 8 views

Répondre

8

La raison en est qu'il peut calculer des offsets de variables pour les sous-classes.

@interface Bird : NSObject { 
    int wingspan; 
} 
@end 
@interface Penguin : Bird { 
    NSPoint nestLocation; 
    Penguin *mate; 
} 
@end 

Sans connaître la structure de la classe « Bird », la classe « Penguin » ne peut pas calculer le décalage de ses champs depuis le début de la structure. La structure de pingouin ressemble un peu à ceci:

struct Penguin { 
    int refcount; // from NSObject 
    int wingspan; // from Bird 
    NSPoint nestLocation; // from Penguin 
    Penguin *mate; // from Penguin 
} 

Cela a un effet secondaire: si vous modifiez la taille d'une classe dans une bibliothèque, vous briser toutes les sous-classes dans les applications liées à cette bibliothèque. Les nouvelles propriétés fonctionnent autour de ce problème.

6

Bien qu'elles soient déclarées dans le fichier d'en-tête, toutes les variables d'instance dans Objective-C ont l'accès @protected par défaut. Cela signifie que la variable est accessible dans la classe qui la déclare et toute classe héritant de cette classe.

Voici la documentation d'Apple sur la définition d'une classe Objective-C: Defining Classes

Notez la section intitulée "La portée des variables d'instance".

3

Tiré de la section de la documentation d'Apple sur la définition des classes Objective-C, The Role of the Interface:

Although instance variables are most naturally viewed as a matter of the implementation of a class rather than its interface, they must nevertheless be declared in the interface file. This is because the compiler must be aware of the structure of an object where it’s used, not just where it’s defined.

6

Je pense qu'il est un problème technique. Si je comprends bien, une classe Objective-C est juste une structure C fantaisie. Et pour qu'une structure soit utilisée, sa taille doit être connue. (Comme comment sizeof() fonctionnerait autrement)

+0

Ils sont juste C struct , pas même ceux de fantaisie :-) donc quelque chose comme anObject-> anIVar fonctionne très bien. Malheureusement, le runtime hérité autorise ce type d'accès même sur les variables @private et ne vomit qu'un avertissement du compilateur: -/ –

2

Notez que sous le nouveau "Modem Runtime" d'Objective C 2.0 (disponible dans les applications iPhone et Mac OS X 10.5 64 bits) vous n'avez pas besoin de spécifier les ivars, vous pouvez spécifier les propriétés, puis utiliser @synthesize pour générer les ivars. Cela s'explique par le fait que dans le moteur d'exécution moderne, les ivars ont un symbole d'indirection global qui contient le décalage pour l'ivar. Cela résout également le problème de classe de base fragile, permettant de réorganiser et d'ajouter des ivars sans nécessiter la recompilation des sous-classes (la suppression ou le renommage des ivars peut toujours provoquer des erreurs de liaison).

Cependant, vous devez toujours lister les propriétés dans l'interface principale, il ne semble donc pas possible de masquer entièrement les ivars privés, ce qui est regrettable. Vous ne pouvez pas, par exemple, utiliser une propriété et @synthesize dans une catégorie.

+0

Vous pouvez cependant déclarer une propriété dans une continuation et @synthesize dans la @implementation principale. –

5

Au cas où quelqu'un tombe par hasard sur cette question - au XCode 4.2 avec le compilateur LLVM, vous pouvez déclarer des variables d'instance dans la @implementation en utilisant la notation accolade suivante:


@interface SomeClass : NSObject 
@end 

@implementation SomeClass { 
    NSString *myInstanceVariable_; 
} 

- (void)moreMethods {} 
@end 

Les variables d'instance ne devrait généralement pas faire partie de vos classes déclarées interface publique - ils sont détails de mise en œuvre.

Cependant, MAKE SURE vous définissez vos variables d'instance dans les accolades ou bien vous serez en train de définir une variable globale qui n'a aucun rapport avec l'instance d'objet:


@implementation SomeClass 
    NSString *whoopsGlobalVariable_; 

- (void)moreMethods {} 

@end 
+0

Je viens d'examiner cela. D'après mes tests, il semble que GCC ne le fera pas; cela donne une erreur: "spécification de variable d'instance incohérente". Il compile uniquement avec LLVM. Voir aussi [Déclaration des variables dans @implementation] (http://stackoverflow.com/questions/7946998/declaring-variables-in-implementation). –

+1

À droite, il nécessite le compilateur LLVM moderne. – sickp

Questions connexes