2010-05-15 4 views
12

que vous avez eu les deux constructeurs suivants:- appeler un constructeur d'un autre

- (id)initWithTitle:(NSString *)title; 
- (id)initWithTitle:(NSString *)title page:(NSString *)page; 

Le second constructeur est pas différent du premier, sauf qu'il met en place la variable membre « page ». Puisqu'il doit essentiellement faire la même chose, y a-t-il un moyen d'appeler le premier à partir du second pour réduire la duplication du code, ou devez-vous mettre en place une troisième méthode pour effectuer les tâches courantes?

Je parle de quelque chose de semblable à cela, même si je doute que cela fonctionne:

- (id)initWithTitle:(NSString *)_title { 
    if(self = [super init]) { 
     self.title = _title; 
    } 

    return self; 
} 

- (id)initWithTitle:(NSString *)_title page:(NSString *)_page { 
    if(self = [self initWithTitle:_title]) { 
     self.page = _page; 
    } 

    return self; 
} 
+2

@phunehehe a une meilleure solution, mais ce que vous avez posté * fonctionnera. –

+0

Euh, je suppose que ça va, maintenant que j'y pense. Merci – synic

+5

Plus tôt vous abandonnerez les termes C++ et commencerez à utiliser les termes Objective-C, plus tôt la documentation commencera à avoir du sens. Objective-C n'a pas de constructeurs ou de variables membres. Il a des initialiseurs et des variables d'instance. – bbum

Répondre

18

Ce que vous dites est bizarre parce que je pense à ce

- (id)initWithTitle:(NSString *)_title { 
    return [self initWithTitle:_title page:nil]; 
} 

- (id)initWithTitle:(NSString *)_title page:(NSString *)_page { 
    if(self = [super init]) { 
     self.title = _title; 
     self.page = _page; 
    } 
    return self; 
} 

Doesn » ça marche?

+0

C'est parfait. Merci! – synic

21

D'abord, vous n'avez pas des constructeurs, vous avez deux initialiseurs:

- (id)initWithTitle:(NSString *)title; 
- (id)initWithTitle:(NSString *)title page:(NSString *)page; 

Comme avec la plupart initializers, l'objectif est de configurer certaines variables d'instance (et non variables membres).

La première étape consiste à identifier votre initialiseur désigné. Dans votre cas, il pourrait être:

- (id)initWithTitle:(NSString *)title page:(NSString *)page; 

Ce qui signifie que - (id)initWithTitle:(NSString *)title; seraient mises en œuvre comme d'autres l'ont décrit:

- (id)initWithTitle:(NSString *)_title { 
    return [self initWithTitle:_title page:nil]; 
} 

Cependant, je recommande contre ce modèle car il rend le sous-classement plus d'erreurs que CA devrait etre. En sous-classe, vous devez toujours remplacer l'initialiseur désigné ou vous devez implémenter un nouvel initialiseur qui appelle l'initialiseur désigné. Évidemment, plus vous avez d'initialiseurs, plus vous risquez d'introduire des bogues dans les sous-classes.

De plus, ceci:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!" page: nil]; 

est beaucoup plus clair que cela:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!"]; 

Le premier indique très précisément que vous avez pensé à page et a décidé de définir explicitement à nil ou autrement compter sur la classe Foo pour définir la page raisonnablement. La seconde ne donne aucune indication de ce genre. Le sous-classement et l'indication explicite de l'intention sont les principales raisons pour lesquelles vous trouverez un manque de telles méthodes pratiques sur Cocoa (il y en a, mais la plupart sont assez anciennes - plus anciennes que quand la politique devenait vraiment la règle).

+2

Vous ne pouvez pas éviter le motif lorsque vous créez une catégorie qui introduit un nouvel initialiseur et que vous souhaitez simplement appeler un initialiseur existant. –

Questions connexes