2010-02-03 3 views
1

J'essaie de créer un objet instanciable uniquement par une méthode d'usine. J'ai empêché init d'être utilisé en lançant une exception (voir Creating a class with no init method). Cependant, cela signifiait que je devais créer une nouvelle méthode secretInit à utiliser dans la méthode d'usine. Cette méthode est désordonnée et bien que nous puissions éviter de déclarer secretInit dans le fichier d'en-tête, quelqu'un pourrait toujours y accéder. Y a-t-il une meilleure solution? Une idée est d'essayer d'appeler directement sur le super objet de URLReqs plutôt que de créer une fonction pour le faire.Objet uniquement initialisable par la méthode usine (Objective-c)

+1

Je pense que votre méthode 'buildURLReq:' est supposée renvoyer 'tmp', pas' nil'. – dreamlax

Répondre

1

Vous ne voulez pas le faire de cette façon, mais il est possible:


#include <objc/message.h> 

@implementation MyClass 

+ (id) factoryMethodWithParameter:(NSString *) someString; 
{ 
    struct objc_super instanceSuper; 
    id myInstance = [self alloc]; 
    instanceSuper.receiver = myInstance; 
    instanceSuper.super_class = [self superclass]; 
// instanceSuper.class = [self superclass]; // use this line if the above doesn't compile 
    myInstance = objc_msgSendSuper (&instanceSuper, @selector(init)); 

    //continue on setting up myInstance's ivars . . . 
    [myInstance setVariable:someString]; 

    return myInstance; 
} 

- (id) init 
{ 
    self = [super init]; 
    if (!self) return nil; 
    [self release]; 
    [self doesNotRecogniseSelector:_cmd]; 
    return nil; 
} 

@end 

Cela vous permettra de continuer à envoyer des messages à init “ super objet ” de myInstance, mais ne permettre à quiconque d'envoyer init à MyClass instances. Attention cependant, bien que ce soit en utilisant les fonctions d'exécution standard déclarées dans objc/*.h, ne vous attendez pas à ce que Apple conserve cette API d'exécution cohérente.

+0

Pourquoi je ne veux pas utiliser cette méthode? – Casebash

+0

Je ne sais pas pourquoi je vous ai dit de ne pas l'utiliser. . . – dreamlax

+0

OH! Il est venu à moi maintenant. Je n'allais pas le recommander parce que c'est spécifique à l'exécution d'Apple. Si, par miracle, 'GNUstep' devenait supportable ou si d'autres runtimes devenaient disponibles, alors cette méthode pourrait ne pas être utilisable pour ces temps d'exécution. Je suppose que vous ciblez Mac OS X et/ou iPhone (je ne sais pas si cela fonctionnera sur iPhone), mais puisque vous avez seulement tagué votre question «objectif-c», je voulais laisser un avertissement. Puis j'ai oublié ce que j'écrivais et j'ai partiellement terminé ma pensée à la fin de ma réponse. – dreamlax

0

La solution consiste à utiliser une catégorie sur votre objet pour masquer la méthode d'initialisation secrète.

Private Methods through categories

Quel but que vous essayez d'accomplir? Il pourrait y avoir une meilleure solution que cela.

+1

Cela ne cache pas la méthode, pas plus que de ne pas la déclarer. Il permet simplement à d'autres méthodes dans la classe de connaître son existence et donc vous n'obtenez pas d'avertissement du compilateur. – Casebash

0

Il ne l'expose que s'il est référencé dans le fichier d'en-tête.

Non, attendez. Je devrais dire cela d'une autre manière. Il n'y a pas de meilleure façon de le cacher que de ne pas le déclarer dans le fichier d'en-tête. Les méthodes privées n'existent pas en Objective-C.

Questions connexes