2013-08-07 11 views
6

Próbuję zrozumieć, który powinien być oznaczony jako inicjator, a który z jednego inicjalizatora wygody. Czytałem dokumenty z Apple na ten temat, ale nadal nie jestem pewien. Czy wyznaczony inicjator musi mieć wszystkie wartości wymagane dla tej klasy? Na przykład
Był to pierwszy wyznaczony initializer że stworzyłWyznaczony inicjator i inicjator wygody w celu-c oraz jak prawidłowo je utworzyć i powiązać ze sobą

-(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck 
{ 
    self = [super init]; 
    if (self) { 
     for(int i = 0; i<=cardCount;i++){ 
      Card *card = [deck drawRandomCard]; 
      if (!card) { 
       self = nil; 
       break; 
      }else{ 
       self.cards[i] = card; 
      } 
     } 
    } 

    return self; 
} 

Teraz Adde cardMatchMode własności do tej klasy i chciałby, aby ustawić go w inicjatora. Aby klasa była kompatybilna wstecz i aby zrozumieć inicjatory, przechowuję tę, którą mam teraz i tworzę kolejny inicjator.

-(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode 
{ 

    _cardMatchMode = matchMode; 
    return [self initWithCardCount:cardCount usingDeck:deck];; 
} 

podstawie docs jabłoni inicjatora wygoda musi zwrócić wartość dla wyznaczonego inicjatora ale pytanie brzmi, czy mogę ustawić dodatkową właściwość w tej klasie w inicjalizatorze wygody? Czy mogę powiedzieć, że self.cardMatchMode = matchMode; lub self nie jest w pełni zainicjalizowany?
To działa, ale ja po prostu chciałem, aby zrozumieć, czy jest to właściwy kod i mogę uzyskać dostępu do właściwości cardMatchMode w init wygody lub I musiałby dokonać -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode

jako wyznaczone inicjatora a drugi wygody init oraz przerobić kod? Dzięki!

///// Aktualizacja

ja otrzymuję błąd w

-(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode 

gdy próbowałem zrobić self = [self initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck*)deck; błąd, że nie można przypisać własny poza rodziną startowej. Rozgryzłem to, co było problemem. Metoda init miała małe litery w i musiała to być kapitał, więc teraz działa. To jest kod, który mam teraz dla mojego inicjatora wygody.

-(id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode 
{ 
    self = [self initWithCardCount:cardCount usingDeck:deck]; 
    if (self){ 
     _cardMatchMode = matchMode; 
    } 
    return self; 
} 

Teraz ma to więcej sensu. Wywołałem wyznaczony init, który wywołuje super, a następnie ustawiam zmienną cardMatchMode.

O ile rozumiem, istnieje wiele obiektów, które mają inicjator wygody z dodatkowymi parametrami i będą po prostu wywoływały inicjalizację. Jeśli spojrzeć na NSString i ma różne inicjatory o różnych parametrach. Prawdopodobnie wywołuje init, który jest wyznaczonym inicjatorem. Czy to jest poprawne?

+0

Słyszałeś o konstruktora przeciążenie? Wyznaczony inicjator jest podobny do tego w Javie jako prawdziwy konstruktor, który przyjmuje większość parametrów. Następnie 'inicjator wygody' wywoła' wyznaczonego inicjatora' do wykonania pracy, to jest wywołaję 'super init'. –

Odpowiedz

6

Według Apple Dokumentacji, wyznaczony initalizer

jest zazwyczaj init ...metoda, która ma najwięcej parametrów i która wykonuje większość pracy inicjującej.

W twoim przypadku będzie to - (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode. Wszystkie inne inicjalizatory będą miały mniej argumentów, wypełniając brak parametrów na wyznaczonym inicjalizatorze z wartościami domyślnymi lub innymi wnioskami.

Tak więc każdy inicjator wygody wywołuje określony inicjator zamiast inicjatora nadklasy.

initializer para Wygoda wyznaczone będzie wyglądać w przypadku:

/** 
Convenience initializers 
*/ 
- (id)init 
{ 
    self = [self initwithCardCount:kDefaultCardCount usingDeck:[Deck defaultDeck] cardMatchMode:kCardMatchModeDefault]; 
    return self; 
} 

- (id)initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck 
{ 
    self = [self initwithCardCount:cardCount usingDeck:deck cardMatchMode:kCardMatchModeDefault]; 
    if (self) { 

    } 

    return self; 
} 

/** 
Designated initializer 
*/ 
- (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode 
{ 
    self = [super init]; 
    if (self) { 
     for (int i = 0; i <= cardCount; i++) { 
      Card *card = [deck drawRandomCard]; 
      if (!card) { 
       self = nil; 
       break; 
      } 
      else { 
       self.cards[i] = card; 
      } 
     } 
     // Set card match mode here: 
     _cardMatchMode = matchMode; 
    } 

    return self; 
} 
+1

Dzięki za odpowiedź. Sprawdź moją zaktualizowaną odpowiedź. W tym przypadku tak naprawdę nie chcę, aby ludzie wywoływali init, ponieważ chcę mieć pewność, że przekazują parametry podczas inicjowania tej klasy. Nie będą domyślne parametry. Na dłuższą metę domyślam się, że nie ma znaczenia, ile parametrów ma wyznaczony i dogodny init, dopóki wyznaczony wywoła super i wygoda zadzwoni wyznaczona. – Yan

15

Wyznaczonym inicjatorem jest ten, który wywołuje wskazany inicjator nadklasy swojej klasy, więc jest to jedyny inicjator wywołujący metodę na obiekcie super. Żaden inny inicjator w klasie nie powinien tego robić; te wtórne inicjatory powinny wywoływać wskazany inicjator przy użyciu self. Zazwyczaj wyznaczony inicjator ma wszystkie parametry niezbędne do utworzenia użytecznego obiektu klasy.

W skrócie, wskazany inicjator jest jedynym, który wywołuje inicjator na super, a wszystkie inne inicjalizatory w klasie wywołują wskazany inicjator (używając self).

+0

Dzięki za odpowiedź. Zaktualizowałem to, co ma teraz większy sens. Jak rozumiem tak długo, jak tylko wyznaczony inicjator wywołuje super, a drugie tylko wywołuje wyznaczony init, który powinien działać. Wszystkie właściwości klasy zostaną zainicjowane przez wywołanie wyznaczone jako pierwsze, a następnie ustawienie reszty w drugorzędnym. – Yan