4 votes

Lorsqu'on surcharge la méthode `init`, pourquoi est-il important de la redéfinir ?

J'ai eu un exercice pour surcharger la méthode init, donc j'ai besoin de créer un fichier init qui définira également certains attributs.

Ma question est la suivante : pourquoi ai-je besoin de définir l'original init au cas où la nouvelle méthode init ne fonctionne pas ?

C'est mon .h fichier :

#import <Foundation/Foundation.h>

#import "XYPoint.h"

@interface Rectangle: NSObject

@property float width, height, tx, ty;

-(XYPoint *) origin;
-(void) setOrigin: (XYPoint *) pt;
-(void) translate: (XYPoint *) point;
-(id) initWithWidth:(int) w andHeight:(int) h;
-(id) init;

@end

Et .m (uniquement les méthodes init) :

-(id) initWithWidth:(int)w andHeight:(int)h
{
    self = [super init];

    if (self)
    {
        [self setWidth:w andHeight:h];
    }

    return self;
}

-(id) init
{
    return [self initWithWidth:0 andHeight:0];
}

Je sais que c'est bien comme ça, mais si quelqu'un peut m'expliquer pourquoi, je l'apprécierais.

5voto

Anurag Points 66470

L'idée est d'avoir un point central d'initialisation pour votre objet au lieu de saupoudrer l'initialisation des variables dans chaque méthode init.

Votre exemple particulier ne rend pas vraiment justice à ce modèle parce que vous initialisez un Rectangle avec une largeur et une hauteur de 0, et que l'implémentation par défaut de NSObject remet la mémoire de toutes les variables d'instance à zéro par défaut, et votre initWithWidth:andHeight: fait la même chose. Toutefois, supposons que vous allouiez par défaut des rectangles unitaires (largeur 1, hauteur 1) lors de la création d'un objet Rectangle à l'aide de la méthode ,

[[Rectangle alloc] init]

alors au lieu de faire ça,

- (id)initWithWidth:(int)width andHeight:(int)height {
    self = [super init];
    if (self) {
        [self setWidth:width andHeight:height];
    }
    return self;
}

- (id)init {
    self = [super init];
    if (self) {
        [self setWidth:1 andHeight:1];
    }
    return self.
}

vous centralisez le point d'initialisation en faisant juste,

- (id)initWithWidth:(int)width andHeight:(int)height {
    self = [super init];
    if (self) {
        [self setWidth:w andHeight:h];
    }
    return self;
}

- (id)init {
    return [self initWithWidth:1 andHeight:1];
}

Ceci va également de pair avec le principe de SEC alias Don't Repeat Yourself.

Il s'agit d'un exemple trivial, mais dans la plupart des objets du monde réel, vous pouvez avoir une configuration beaucoup plus complexe avec l'enregistrement de notifications, l'enregistrement de KVO, etc. et il devient alors absolument crucial de centraliser toute cette logique d'initialisation.

2voto

Jasper Blues Points 7262

Vous n'avez pas à le faire. Vous avez généralement un initialisateur qui appelle super (self = [super initWithXX]) et les autres s'y réfèrent.

Dans votre exemple spécifique ci-dessus, c'est une bonne idée parce que initWithWidth:andHeight agit comme l'initialisateur principal, donc si vous appelez la valeur par défaut, tout code qui doit être exécuté dans l'initialisateur principal sera appelé.

Btw : l'utilisation du mot 'and' dans les paramètres de l'initialisateur est un peu archaïque au regard des conventions Objective-C modernes.

Prograide.com

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.

Powered by:

X