2010-12-27 14 views
7

Mam dwie różne metody inicjowania mojej klasy cel-c. Jedna jest wartością domyślną, a jedna przyjmuje parametr konfiguracyjny. Teraz jestem całkiem zielony, jeśli chodzi o cel c, ale wdrożyłem te metody i zastanawiam się, czy istnieje lepszy (bardziej poprawny/w dobrym stylu) sposób radzenia sobie z inicjalizacją niż sposób, w jaki to zrobiłem . Czy napisałem te funkcje inicjalizacyjne zgodnie ze standardami i dobrym stylem? Po prostu nie ma sensu sprawdzać istnienia selfPtr, a następnie zwracać na podstawie tego.celem-c domyślna metoda init dla klasy?

Poniżej znajdują się pliki nagłówkowe i pliki implementacji klas. Ponadto, jeśli zauważysz coś, co jest złe lub złe, daj mi znać. Jestem programistą C++/Javascript, który uczy się celów-c jako hobby i byłby wdzięczny za wszelkie wskazówki, które mógłbyś zaoferować.

#import <Cocoa/Cocoa.h> 

// class for raising events and parsing returned directives 

@interface awesome : NSObject { 
// silence is golden. Actually properties are golden. Hence this emptiness. 
} 

// properties 
@property (retain) SBJsonParser* parser; 
@property (retain) NSString* eventDomain; 
@property (retain) NSString* appid 

// constructors 
-(id) init; 
-(id) initWithAppId:(id) input; 

// destructor 
-(void) dealloc; 


@end 

#import "awesome.h" 
#import "JSON.h" 


@implementation awesome 



- (id) init { 
if (self = [super init]) { 
    // if init is called directly, just pass nil to AppId contructor variant 
    id selfPtr = [self initWithAppId:nil]; 
} 

if (selfPtr) { 
    return selfPtr; 
} else { 
    return self; 
} 
} 

- (id) initWithAppId:(id) input { 
if (self = [super init]) { 
    if (input = nil) { 
    input = [[NSString alloc] initWithString:@"a369x123"]; 
    } 
    [self setAppid:input]; 
    [self setEventDomain:[[NSString alloc] initWithString:@"desktop"]]; 
} 
return self; 
} 

// property synthesis 
@synthesize parser; 
@synthesize appid; 
@synthesize eventDomain; 

// destructor 
- (void) dealloc { 
self.parser = nil; 
self.appid = nil; 
self.eventDomain = nil; 
[super dealloc]; 
} 

@end 

Dzięki!

+1

Jednym ze szczególnych problemów, które widzę, jest to, że jeśli użyto 'init', to' [super init] 'jest wywoływane dwa razy. – dreamlax

+2

Przeciekłeś również właściwość 'eventDomain', ponieważ tworzysz obiekt z +1 liczbą własności i nadajesz mu metodę, która zwiększa liczbę własności do +2, twoja metoda dealloc przywraca ją do +1.Powinno być 0 w stosunku do twojego obiektu 'awesome'. – dreamlax

+0

Co więcej, dołączenie "Cocoa/Cocoa.h" dotyczy systemu Mac OS X, a nie systemu iOS. – jer

Odpowiedz

14

Kiedy jeden inicjator po prostu wykonuje bardziej złożony inicjator z niektórych parametrów domyślnych, nazywają go jako takie:

-(id)init { 
    return [self initWithAppID:nil]; 
} 

-(id)initWithAppID:(id)input { 
    if (self = [super init]) { 
    /* perform your post-initialization logic here */ 
    } 
    return self; 
} 

Zazwyczaj spróbuj uczynić jeden z inicjalizatorów "wyznaczonym inicjatorem", co oznacza, że ​​zawsze jest wywoływany. W tym przypadku jest to -initWithAppID:.

0

Szczerze mówiąc, uważam to za punkt sporny. Twoja druga metoda inicjalizacji nie ma sensu, gdy otrzymuje się argument zerowy (plus masz problem logiczny w warunkowym sprawdzaniu, czy wejście jest zerowe). W tym przypadku powinienem podać jedną metodę inicjalizacji i dwie metody klasy fabryki, które działają w zwykły sposób: zwracaj autoreleased instancje, a w jednej z nich podaj wartość domyślną.

Na przykład zadeklarować metody klasy:

+ (awesome*)awesome; 
+ (awesome*)awesomeWithAppId:(id)foo; 

i implementacji dla +awesome na przykład napisać to tak:

+ (awesome*)awesome 
{ 
    return [[[awesome alloc] initWithAppId:@"a369x123"] autorelease]; 
} 

i podobnie, w awesomeWithAppId: coś takiego:

+ (awesome*)awesomeWithAppId:(id)foo 
{ 
    return [[[awesome alloc] initWithAppId:foo] autorelease]; 
} 

To może być po prostu ja.

0

default będzie którykolwiek z nich wybrać, aby zadzwonić,

[awesome alloc] init]; 
[awesome alloc] initWithAppId:ID]; 
1

Twoja metoda init powinna wywoływać preferowany inicjator, initWithAppId :, zamiast super implementacji. Następnie initWithAppId wywołuje super implementację, tak jak to robi. Ponadto, w initWithAppId: masz (input = nil), który zawsze ustawi wejście na zero i oceni na YES. Oto odpowiednie implementacje.

- (id)init { 
    return [self initWithAppId:nil]; 
} 
- (id)initWithAppId:(id)input { 
    if((self = [super init])) { 
     if(input == nil) input = @"a369x123"; 
     self.appid = input; 
     self.eventDomain = @"desktop"; 
    } 
    return self; 
} 
Powiązane problemy