2010-11-24 9 views

Répondre

15

Techniquement, non. Les propriétés ne sont en réalité que des méthodes et toutes les méthodes sont publiques. La façon dont nous "protégeons" les méthodes dans Objective-C est de ne pas en informer les autres.

Pratiquement, oui. Vous pouvez définir les propriétés dans une extension de classe, et toujours @synthesize dans votre bloc d'implémentation principal.

+1

Pour être "protégée", l'interface d'extension de classe doit se trouver dans un fichier d'en-tête distinct à inclure dans la classe et ses sous-classes. – JeremyP

+0

Pour autant que je sache, toutes les propriétés déclarées dans l'extension d'interface de classes de base ne sont pas disponibles pour les sous-classes - elles ont une portée privée, non protégée. Voir cette discussion SO: http://stackoverflow.com/questions/5588799/objective-c-how-do-you-access-parent-properties-from-subclasses – memmons

+0

@Harkonian si vous déclarez le sélecteur vous-même, vous pouvez toujours appeler il. Il n'y a pas de «protection» d'une méthode autre que le simple fait de cacher sa déclaration. Objective-C n'a pas le concept de méthodes protégées ou privées. Seulement ivars protégés ou privés. –

0

Vous pouvez utiliser cette syntaxe dans l'implémentation de sous-classe.

@interface SuperClass (Internal) 

@property (retain, nonatomic) NSString *protectedString; 

@end 
+1

Pouvez-vous ajouter une courte explication sur le fonctionnement de cette solution? – HairOfTheDog

9

Ceci est possible en utilisant une extension de classe (pas de catégorie) que vous incluez dans les fichiers de mise en œuvre à la fois la classe de base et les sous-classes.

Une extension de classe est définie similaire à une catégorie, mais sans le nom de la catégorie:

@interface MyClass() 

Dans une extension de classe, vous pouvez rapporter des propriétés, qui sera en mesure de synthétiser les Ivars d'appui (XCode> 4.4 la synthèse automatique des ivars fonctionne également ici). Dans la classe d'extension, vous pouvez remplacer/affiner les propriétés (modifier readonly en readwrite, etc.) et ajouter des propriétés et des méthodes qui seront "visibles" aux fichiers d'implémentation (mais notez que les propriétés et les méthodes ne sont pas vraiment privé et peut encore être appelé par le sélecteur).

D'autres ont proposé d'utiliser un fichier séparé d'en-tête MyClass_protected.h pour cela, mais cela peut aussi être fait dans le fichier principal d'en-tête en utilisant #ifdef comme ceci:

Exemple:

BaseClass.h

@interface BaseClass : NSObject 

// foo is readonly for consumers of the class 
@property (nonatomic, readonly) NSString *foo; 

@end 


#ifdef BaseClass_protected 

// this is the class extension, where you define 
// the "protected" properties and methods of the class 

@interface BaseClass() 

// foo is now readwrite 
@property (nonatomic, readwrite) NSString *foo; 

// bar is visible to implementation of subclasses 
@property (nonatomic, readwrite) int bar; 

-(void)baz; 

@end 

#endif 

BaseClass.m

// this will import BaseClass.h 
// with BaseClass_protected defined, 
// so it will also get the protected class extension 

#define BaseClass_protected 
#import "BaseClass.h" 

@implementation BaseClass 

-(void)baz { 
    self.foo = @"test"; 
    self.bar = 123; 
} 

@end 

ChildClass.h

// this will import BaseClass.h without the class extension 

#import "BaseClass.h" 

@interface ChildClass : BaseClass 

-(void)test; 

@end 

ChildClass.m

// this will implicitly import BaseClass.h from ChildClass.h, 
// with BaseClass_protected defined, 
// so it will also get the protected class extension 

#define BaseClass_protected 
#import "ChildClass.h" 

@implementation ChildClass 

-(void)test { 
    self.foo = @"test"; 
    self.bar = 123; 

    [self baz]; 
} 

@end 

Lorsque vous appelez #import, il copie des pâtes essentiellement le fichier .h à l'endroit où vous l'importer. Si vous avez un #ifdef, il inclura uniquement le code à l'intérieur si le #define avec ce nom est défini.

Dans votre fichier .h, vous ne définissez pas la définition de manière à ce que les classes qui importent ce fichier .h ne voient pas l'extension de classe protégée. Dans le fichier .m de la classe de base et de la sous-classe, vous utilisez #define avant d'utiliser #import afin que le compilateur inclue l'extension de classe protégée.

Questions connexes