Généralement dans Objective-C, vous créez un initialiseur désigné pour chaque classe, puis les sous-classes utilisent le même initialiseur. Donc, au lieu d'utiliser initAnimal et initDog, vous utilisez simplement init. La sous-classe de chien alors définir sa propre méthode d'initialisation et d'appeler l'initialiseur désigné dans sa classe parente:
@implementation Dog
-(id)init
{
if((self = [super init])) { // call init in Animal and assign to self
// do something specific to a dog
}
return self;
}
@end
Vous n'avez pas vraiment de préciser initDog et initAnimal parce que la classe est déclarée sur le côté droit de la cession ...
Mise à jour: J'ajoute ce qui suit à la réponse afin de refléter les informations supplémentaires dans la question
Il y a plusieurs façons de faire en sorte que les sous-classes ne remettent pas initializers autres que leur initialiseur désigné et la façon dont vous ultimat Le choix d'Ely sera basé en grande partie sur votre conception entière. L'une des bonnes choses à propos d'Objective-C, c'est que c'est tellement flexible. Je vais vous donner deux exemples pour vous aider à démarrer. En premier lieu, si vous créez une sous-classe ayant un initialiseur différent de celui de sa classe parente, vous pouvez surcharger l'initialiseur du parent et lancer une exception. Cela permettra aux programmeurs de savoir immédiatement qu'ils ont violé le protocole de votre classe ... cependant, il devrait être indiqué que vous devriez avoir une bonne raison de le faire et qu'il devrait être très bien documenté que la sous-classe peut n'utilise pas le même initialiseur que la superclasse.
@implementation Dog
-(id)init
{
// Dog does not respond to this initializer
NSAssert(false, @"Dog classes must use one of the designated initializers; see the documentation for more information.");
[self autorelease];
return nil;
}
-(id)initWithFur:(FurOptionsType)furOptions
{
if((self = [super init])) {
// do stuff and set up the fur based on the options
}
return self;
}
@end
Une autre façon de le faire est d'avoir un initialiseur plus comme votre exemple original. Dans ce cas, vous pouvez changer l'init par défaut de la classe parente pour toujours échouer. Vous pouvez ensuite créer un initialiseur privé pour votre classe parente, puis vous assurer que tout le monde appelle l'initialiseur approprié dans les sous-classes.Ce cas est évidemment plus compliqué:
@interface Animal : NSObject
-(id)initAnimal;
@end
@interface Animal()
-(id)_prvInitAnimal;
@end
@interface Dog : Animal
-(id)initDog;
@end
@implementation Animal
-(id)init
{
NSAssert(false, @"Objects must call designated initializers; see documentation for details.");
[self autorelease];
return nil;
}
-(id)initAnimal
{
NSAssert([self isMemberOfClass:[Animal class]], @"Only Animal may call initAnimal");
// core animal initialization done in private initializer
return [self _prvInitAnimal];
}
-(id)_prvInitAnimal
{
if((self = [super init])) {
// do standard animal initialization
}
return self;
}
@end
@implementation Dog
-(id)initDog
{
if((self = [super _prvInitAnimal])) {
// do some dog related stuff
}
return self;
}
@end
Ici vous voyez l'interface et l'implémentation de la classe Animal et Chien. L'Animal est l'objet de premier niveau désigné et remplace donc l'implémentation de init de NSObject. Toute personne qui appelle init sur une sous-classe Animal ou l'une de ses sous-classes recevra une erreur d'assertion en les renvoyant à la documentation. Animal définit également un initialiseur privé sur une catégorie privée. La catégorie privée resterait avec votre code et les sous-classes d'Animal appelleraient cet initialiseur privé quand ils appellent super. Son but est d'appeler init sur la super-classe d'Animal (NSObject dans ce cas) et de faire toute initialisation générique qui pourrait être nécessaire. Enfin, la première ligne de la méthode initAnimal d'Animal est une affirmation que le récepteur est en fait un animal et non une sous-classe. Si le récepteur n'est pas un animal, le programme échouera avec une erreur d'assertion et le programmeur sera référé à la documentation.
Ce ne sont que deux exemples de la façon dont vous pourriez concevoir quelque chose avec vos besoins spécifiques. Cependant, je voudrais fortement vous suggérer de considérer vos contraintes de conception et voir si vous avez vraiment besoin de ce type de design car il est non standard dans Cocoa et dans la plupart des cadres de conception OO. Par exemple, vous pouvez envisager de créer des objets au niveau de la racine de divers animaux et simplement avoir un protocole Animal, exigeant que tous les différents "animaux" répondent à certains messages animaux-génériques. De cette façon, chaque animal (et les vraies sous-classes d'Animal) peuvent eux-mêmes gérer leurs initialiseurs désignés et ne pas avoir à se fier à des superclasses se comportant de manière si spécifique et non standard.
Okay Zoul, J'ai fait des mises à jour à ma réponse en fonction des mises à jour de votre question ... c'est assez long maintenant, mais j'espère que cela vous donne une idée de ce que vous cherchiez. –
Comme il s'agit d'un résultat supérieur. La réponse en XCode moderne, vous pouvez réaliser cela avec NS_UNAVAILABLE. Voir: http://stackoverflow.com/questions/195078/is-it-possible-to-make-the-init-method-private-in-objective-c#answer-27693034 – m4js7er