2010-06-26 4 views
0

Dans un fichier d'en-tête comme celui-ci, quand une variable d'instance serait-elle utilisée et quand une propriété serait-elle utilisée?Quand une variable d'instance serait-elle utilisée et quand une propriété serait-elle utilisée?

Doivent-ils avoir le même nom?

#import <UIKit/UIKit.h> 

@class BlueViewController; 
@class YellowViewController; 

@interface SwitchViewController : UIViewController { 
    YellowViewController *yellowViewController; 
    BlueViewController *blueViewController; 
} 

@property (retain, nonatomic) YellowViewController *yellowViewController; 
@property (retain, nonatomic) BlueViewController *blueViewController; 

@end 

Répondre

4

Une déclaration @property crée simplement des méthodes accesseurs pour un Ivar. Les propriétés n'ont donc pas vraiment de noms, seules les méthodes accesseurs le font; et ceux-ci ne doivent pas avoir le même nom que l'ivar. En fait, ils n'ont même pas besoin d'un ivar correspondant.

Vous pouvez modifier les noms des méthodes utilisant les getter et setter décorateurs comme ceci:

@property (assign, getter=isValid) BOOL valid; 

Maintenant, comme je l'ai dit, une déclaration @property crée simplement des méthodes accesseurs pour un Ivar. Vous utilisez donc les propriétés lorsque vous voulez des méthodes d'accesseur. Voici quelques raisons pour lesquelles vous voudrez peut-être des méthodes accesseurs:

  1. Encapsulation (une propriété peut être annoncé comme un type différent de celui Ivar, ou peut ne pas avoir même un Ivar)

  2. changements d'état connexes (modifier un autre Ivar ou invoquer une méthode lorsqu'un Ivar est modifié)

  3. Vous pouvez utiliser le décorateur retain et @synthesize la propriété pour obtenir la gestion de la mémoire beaucoup plus simple

  4. Vous pouvez utiliser atomic décorateur (ou tout simplement pas utiliser le décorateur nonatomic, puisque les propriétés sont atomiques par défaut) pour créer des propriétés atomiques

Voici un exemple pour illustrer les points 1 et 2:

@interface Foo : NSObject { 
    @private 
    int flags; 
    // Humpty and Dumpty are mutually exclusive 
    BOOL humpty; 
    BOOL dumpty; 
} 

@property (nonatomic) BOOL flagA; 
@property (nonatomic) BOOL flagB; 
@property (nonatomic) BOOL humpty; 
@property (nonatomic) BOOL dumpty; 
@property (nonatomic, readonly, getter=isClean) BOOL clean; 

@end 

@implementation Foo 

@synthesize humpty, dumpty; // Synthesize the getters, but provide the setters 

- (void)setHumpty:(BOOL)value { 
    if(value && dumpty) 
     dumpty = NO; 

    humpty = value; 
} 

- (void)setDumpty:(BOOL)value { 
    if(value && humpty) 
     humpty = NO; 

    dumpty = value; 
} 

- (BOOL)flagA { 
    return flags & 0x01; 
} 

- (void)setFlagA:(BOOL)value { 
    if(value) 
     flags |= 0x01; 
    else 
     flags &= ~0x01; 
} 

- (BOOL)flagB { 
    return flags & 0x02; 
} 

- (void)setFlagB:(BOOL)value { 
    if(value) 
     flags |= 0x02; 
    else 
     flags &= ~0x02; 
} 

// Making this a property doesn't really make sense 
// but I'm just trying to demonstrate what you can do 
// with properties 
- (BOOL)isClean { 
    return flags == 0; 
} 

@end 
+0

+1 Pour plus de clarté et de bel exemple. Peut-être le ivar «propre» embrouille-t-il l'eau? – walkytalky

+0

@walkytalky: Oui, j'ai remarqué que je ne l'avais même pas utilisé (j'avais autre chose en tête), alors je l'ai supprimé. –

0

Ils peuvent avoir le même nom, bien qu'ils ne le doivent pas. En effet, il n'est pas nécessaire que la propriété visible à l'extérieur corresponde exactement à une seule variable d'instance. Une telle correspondance est attendue si vous allez à @synthesize les méthodes d'accesseur, mais il y a des raisons tout à fait légitimes pour créer les méthodes manuellement et les faire faire autre chose que de simplement obtenir/fixer un ivar correspondant.

Les variables d'instance n'étant normalement pas accessibles depuis le monde extérieur, tous les accès externes doivent être effectués via les méthodes de propriété. (Il est possible de déclarer des ivars @public, mais c'est rarement une bonne idée.)

De l'intérieur de l'objet, que vous accédiez en tant que propriétés ou variables d'instance dépend de ce que sont réellement les propriétés et de ce que vous en faites .

Pour les propriétés simples synthétisés, il est courant d'utiliser les accesseurs (soit en utilisant explicitement [self setXxx] ou en utilisant la notation de points comme self.xxx) sauf dans dealloc (et peut-être init, en fonction de qui vous demandez).

Dans les cas plus complexes, vous devez vraiment penser à ce que vous essayez d'accomplir. Mais si vous avez pris la peine d'en faire des propriétés, vous voulez probablement que la fonctionnalité encapsulée dans les méthodes d'accès soit appelée la plupart du temps.

En tout cas, lisez le properties documentation pour avoir une meilleure compréhension de ce qui se passe.

0

Vous voulez utiliser les propriétés de tous vos accès externes pour fournir encapsulation, c'est à vous de décider si vous voulez les utiliser en interne, je pense que c'est une question de goût. En utilisant les propriétés de l'extérieur de votre classe, vous pouvez par exemple faire quelques loading paresseux et il devient beaucoup plus facile de faire des changements d'API potentiels en fournissant des avertissements de dépréciation dans les getters/setters.

Questions connexes