J'ai essayé de trouver une solution de contournement pour déclarer les propriétés @protected dans Objective-C afin que seules les sous-classes de la hiérarchie puissent y accéder (en lecture seule et non en écriture). J'ai lu qu'il n'y a pas de méthode documentée de le faire. C'est pourquoi j'ai pensé à cette solution de contournement et je voulais demander l'avis de StackOverflow à ce sujet.
Chaque classe personnalisée en haut de la hiérarchie contient trois classes, une implémentation et deux interfaces. Nommez-les:
ClassA.h
ClassA_protected.h
ClassA.m
Alors n'importe quelle sous-classe de cette classeA serait comme d'habitude:
ClassB.h
ClassB.m
J'ai d'abord créé l'interface ClassA.h où je déclare une variable int protégée de sorte que toute sous-classe de ClassA puisse y accéder:
@interface ClassA : NSObject{
@protected
int _myProtectedInt;
}
@end
La prochaine étape est la solution de contournement dont je parlais. Cependant, une fois que vous l'avez lu, vous verrez qu'il est assez simple. J'ai déclaré une deuxième interface appelée ClassA_protected.h qui fonctionne réellement comme une extension de ClassA.h et nous permet de baliser la propriété comme suit: readonly
:
#import "ClassA.h"
@interface ClassA ()
@property (nonatomic , readonly) int myProtectedInt;
@end
La dernière étape de la préparation de la hiérarchie protégée consiste à déclarer son implémentation dans ClassA.m où nous synthétisons uniquement notre propriété:
#import "ClassA_protected.h"
@implementation ClassA
@synthesize myProtectedInt = _ myProtectedInt;
@end
Ainsi, chaque classe devant constituer une sous-classe de ClassA.h importera plutôt ClassA_protected.h. Ainsi, un enfant comme, par exemple, ClassB.h, serait comme suit:
#import "ClassA_protected.h"
@interface ClassB : ClassA
@end
Et un exemple d'accès à cette propriété à partir de l'implémentation de ClassB.m:
@implementation ClassB
-(void) method {
//edit protected variable
_myProtectedInt= 1;
//normal access
self.muProtectedInt;
}
@end
Bien sûr, cela fonctionne bien. Apple utilise la même approche, par exemple dans la classe UIGestureRecognizer
. Les sous-classes doivent importer le fichier UIGestureRecognizerSubclass.h
supplémentaire et remplacer les méthodes déclarées dans ce fichier.
Pour des "propriétés" simples, utilisez simplement ivar. C'est aussi bon que les propriétés à toutes fins pratiques.
De plus, la valeur par défaut est déjà protégée.
Si vous demandez un avis, c’est le mien: Si l’on décide de muter votre
_myProtectedInt
il réussira probablement quand même, car c'est certainement possible avec le runtime d'Objective-C. Sauf que, votre solution est tout à fait correcte.
Importez l'en-tête protégé dans l'implémentation uniquement. par exemple.
ClassB.h
#import "ClassA.h"
@interface ClassB : ClassA
@end
ClassB.m
#import "ClassA_protected.h"
@implementation ClassB
@end
Et dans un cadre, l'en-tête protégé doit être marqué projet afin qu'il ne soit pas inclus dans les en-têtes publics du cadre. Apple utilise généralement le suffixe _Internal.h pour ses méthodes protégées.
Pour init ou outrepasser une propriété get paresseuse, vous devez avoir un accès direct à l'ivar @proteced. Toutefois, pour votre utilisation, il est préférable de redéclarer la propriété en tant que readwrite, vous pouvez alors tirer parti de toutes les fonctionnalités du setter, atomicity par exemple. .