Je dois masquer (rendre privé) la méthode -init
de ma classe dans Objective-C.
Comment puis je faire ça?
Je dois masquer (rendre privé) la méthode -init
de ma classe dans Objective-C.
Comment puis je faire ça?
unavailable
Ajouter l' unavailable
d'attribut à l'en-tête de générer une erreur de compilation sur tout appel à init.
-(instancetype) init __attribute__((unavailable("init not available")));
Si vous n'avez pas de raison, il suffit de taper __attribute__((unavailable))
, ou même __unavailable
:
-(instancetype) __unavailable init;
doesNotRecognizeSelector:
Utiliser doesNotRecognizeSelector:
d'élever un NSInvalidArgumentException. "Le système d'exécution appelle cette méthode chaque fois qu'un objet reçoit un aSelector message qu'il ne peut pas répondre ou transférer."
- (instancetype) init {
[self release];
[super doesNotRecognizeSelector:_cmd];
return nil;
}
NSAssert
Utiliser NSAssert
de jeter NSInternalInconsistencyException et affiche un message:
- (instancetype) init {
[self release];
NSAssert(false,@"unavailable, use initWithBlah: instead");
return nil;
}
raise:format:
Utiliser raise:format:
de lancer votre propre exception:
- (instancetype) init {
[self release];
[NSException raise:NSGenericException
format:@"Disabled. Use +[[%@ alloc] %@] instead",
NSStringFromClass([self class]),
NSStringFromSelector(@selector(initWithStateDictionary:))];
return nil;
}
[self release]
est nécessaire parce que l'objet était déjà alloc
- indiqué. Lors de l'utilisation de l'ARC, le compilateur vous appeler. En tout cas, pas quelque chose à se soucier lorsque vous êtes sur le point de faire intentionnellement arrêter l'exécution.
objc_designated_initializer
Dans le cas où vous avez l'intention de désactiver init
pour forcer l'utilisation d'un désignée d'initialiseur, il y a un attribut pour que:
-(instancetype)myOwnInit NS_DESIGNATED_INITIALIZER;
Cela génère un avertissement, à moins que tout autre initialiseur les appels de méthode myOwnInit
en interne. Les détails seront publiés dans l'Adoption Moderne Objective-C , après la prochaine Xcode version (je suppose).
Objective-C, comme Smalltalk, n'a pas de notion de "privé" et "public". Tout message peut être envoyé à n'importe quel objet à tout moment.
Ce que vous pouvez faire est de jeter un NSInternalInconsistencyException
si vos -init
méthode est appelée:
- (id)init {
[self release];
@throw [NSException exceptionWithName:NSInternalInconsistencyException
reason:@"-init is not a valid initializer for the class Foo"
userInfo:nil];
return nil;
}
L'autre alternative, ce qui est probablement bien mieux dans la pratique - est de s' -init
faire quelque chose d'intelligent pour votre classe si possible.
Si vous essayez de le faire parce que vous êtes à essayer de "s'assurer" un objet singleton est utilisé, ne vous embêtez pas. Plus précisément, ne vous embêtez pas avec le champ "remplacer +allocWithZone:
, -init
, -retain
, -release
" méthode de création des singletons. Il est presque toujours inutile et est juste que l'ajout de complications pour pas de réel avantage significatif.
Au lieu de cela, il suffit d'écrire votre code tel que votre +sharedWhatever
méthode est la manière dont vous accédez à un singleton, et le document que comme le moyen d'obtenir l'instance du singleton dans votre en-tête. Cela devrait être tout ce dont vous avez besoin dans la grande majorité des cas.
Si vous parlez de la valeur par défaut-méthode init, alors vous ne pouvez pas. Il est hérité de NSObject et chaque classe de se répondre à elle avec aucun avertissement.
Vous pouvez créer une nouvelle méthode, disons -initMyClass, et les mettre dans une catégorie comme Matt suggère. Ensuite, de définir la valeur par défaut-init méthode pour lever une exception si elle ou (mieux), appelez votre privé initMyClass avec certaines valeurs par défaut.
L'une des principales raisons pour lesquelles les gens semblent vouloir cacher init est pour les objets singleton. Si c'est le cas, alors vous n'avez pas besoin de cacher -init, il suffit de retourner l'objet singleton à la place (ou le créer s'il n'existe pas encore).
Cela dépend de ce que tu veux dire par "privé". En Objective-C, l'appel d'une méthode sur un objet peut mieux être décrit comme l'envoi d'un message à l'objet. Il n'y a rien dans la langue, qui interdit à un client à partir de l'appel à la méthode donnée sur un objet; le meilleur que vous pouvez faire est de ne pas déclarer la méthode dans le fichier d'en-tête. Si un client appelle toutefois le "privé" avec la signature à droite, il va encore s'exécuter lors de l'exécution.
Cela dit, la façon la plus courante de créer une méthode privée en Objective-C est de créer une Catégorie dans le fichier d'implémentation, et de déclarer tous les "cachés" méthodes là-bas. Rappelez-vous que ce ne sera pas vraiment empêcher les appels d' init
de la course, mais le compilateur va cracher des avertissements si quelqu'un essaie de le faire.
MyClass.m
@interface MyClass (PrivateMethods)
- (NSString*) init;
@end
@implementation MyClass
- (NSString*) init
{
// code...
}
@end
Il y a un décent thread sur MacRumors.com à propos de ce sujet.
et bien, le problème pourquoi vous ne pouvez pas le faire "privé/invisible" est la cause de la méthode init est envoyé à l'id (alloc retourne un identifiant (id) de ne pas YourClass
Notez que du point de le compilateur (checker) une identification de potencialy répondre à tout ce qui a été tapé (il ne peut pas vérifier ce qui se passe vraiment à l'id au moment de l'exécution), de sorte que vous pouvez le cacher init seulement quand rien nulle part (public = en-tête) utilisent une méthode init, de les compiler le sait, qu'il n'existe aucun moyen pour l'id de répondre à init, car il n'y a pas d'init n'importe où (dans votre source, de toutes les libs etc...)
si vous ne pouvez pas interdire à l'utilisateur de passer d'initialisation et se fait croquer par le compilateur... mais ce que vous pouvez faire, est d'empêcher l'utilisateur de se faire une véritable instance par l'appel d'une init
tout simplement par la mise en œuvre de l'init, qui renvoie nil et ont un (privé / invisible) initialiseur qui nom de quelqu'un d'autre n'obtiendrez pas (comme initOnce, initWithSpecial ...)
static SomeClass * SInstance = nil;
- (id)init
{
// possibly throw smth. here
return nil;
}
- (id)initOnce
{
self = [super init];
if (self) {
return self;
}
return nil;
}
+ (SomeClass *) shared
{
if (nil == SInstance) {
SInstance = [[SomeClass alloc] initOnce];
}
return SInstance;
}
Remarque : que quelqu'un pourrait le faire
SomeClass * c = [[SomeClass alloc] initOnce];
et il serait, en effet, renvoyer une nouvelle instance, mais si le initOnce serait nulle part dans notre projet public (en-tête) a déclaré, il génère un avertissement (id peut ne pas répondre ...) et de toute façon la personne à l'aide de cette, aurait besoin de savoir exactement ce que le réel de l'initialiseur est le initOnce
nous pourrions empêcher, mais il n'est pas nécessaire
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.