2010-05-15 14 views
12

Sagen Sie bitte die folgenden beiden Konstrukteure hatten:Objective-C - Aufruf einen Konstruktor aus einem anderen

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

Der zweite Konstruktor nicht anders als der erste ist, mit der Ausnahme, dass sie die Membervariable „Seite“ einrichtet.

Da es im Grunde dasselbe tun muss, gibt es eine Möglichkeit, die erste von der zweiten zu nennen, um die Codeverdopplung zu reduzieren, oder muss man eine dritte Methode für die üblichen Aufgaben einrichten?

Ich spreche über etwas Ähnliches wie das, obwohl ich das bezweifeln funktioniert:

- (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 hat eine bessere Lösung, aber was du gepostet hast * wird * funktionieren. –

+0

Huh, ich denke es wird jetzt, wo ich darüber nachdenke. Danke – synic

+5

Je eher Sie die C++ - Begriffe fallen lassen und anfangen, die Objective-C-Begriffe zu verwenden, desto früher wird die Dokumentation sinnvoller. Objective-C hat keine Konstruktoren oder Membervariablen. Es hat Initialisierer und Instanzvariablen. – bbum

Antwort

18

Was Sie sagen, ist komisch, weil ich dieses

- (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 denke‘ t es funktioniert?

+0

Das ist perfekt. Vielen Dank! – synic

21

Zuerst Sie nicht Konstrukteure haben Sie zwei initializers haben:

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

Wie bei den meisten initializers, das Ziel ist, einige Instanzvariablen Setup (nicht Membervariablen).

Der erste Schritt besteht darin, Ihren Initialisierer zu identifizieren. In Ihrem Fall könnte es sein:

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

was bedeutet, dass - (id)initWithTitle:(NSString *)title; wie andere umgesetzt würden beschrieben:

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

Allerdings würde ich gegen dieses Muster empfehlen, da es mehr Fehler Subklassen anfällig macht als es sollte sein. Bei der Unterklassenbildung müssen Sie immer den angegebenen Initialisierer oder überschreiben. Sie müssen einen neuen Initialisierer implementieren, der den designierten Initialisierer aufruft. Je mehr Initialisierer Sie haben, desto größer ist das Potenzial für Fehler in der Unterklasse. Außerdem

, dies:

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

ist viel klarer als das:

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

Die erste ganz speziell darauf hinweisen, dass Sie gedacht haben, über page und beschlossen, es explizit zu setzen, um nil oder auf andere Weise verlassen Sie sich auf die Klasse Foo, um die Seite vernünftig einzustellen. Die zweite gibt keinen solchen Hinweis.

Sowohl Subklassenbildung als auch explizite Angabe der Absicht sind die Hauptgründe, warum Sie in Cocoa (wie es einige sind, aber die meisten sind ziemlich alt - älter als zu dem Zeitpunkt, als die Richtlinie wirklich zur Regel wurde) einen Mangel an Convenience-Methoden finden.

+2

Sie können das Muster nicht vermeiden, wenn Sie eine Kategorie erstellen, die einen neuen Initialisierer einführt und Sie einfach einen vorhandenen Initialisierer aufrufen möchten. –

Verwandte Themen