2013-08-07 5 views
6

Я пытаюсь понять, какой из них следует обозначать как инициализатор и какой один инициализатор удобства. Я читал документы яблока по этой теме, но я все еще не уверен. Должен ли назначенный инициализатор иметь все значения, которые требуются для класса? Например
Это был первым назначенным инициализатор, что я создалНазначенный инициализатор и инициализатор удобства в объективе-c и как правильно их создать и связать вместе

-(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; 
} 

Теперь ADDE cardMatchMode свойства этого класса и хотел бы установить его в инициализаторе. Чтобы сделать класс обратно совместимым и понять инициализаторы, я сохраняю тот, который у меня есть, и создаю другой инициализатор.

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

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

на основе яблочных документации удобство инициализатор должен возвращать значение для назначенного инициализаторе но вопрос может я установить дополнительное свойство этого класса в удобстве инициализаторе? Могу ли я сказать self.cardMatchMode = matchMode; или сам еще не полностью инициализирован?
Это делает работу, но я просто хотел бы понять, если это правильный код, и я могу получить доступ к свойству cardMatchMode в удобстве инициализации или я должен был бы сделать -(id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode

в качестве назначенного инициализатора и другой один удобство инициализации и переделать код? Благодаря!

///// Update

Я получаю сообщение об ошибке в

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

Когда я попытался сделать self = [self initWithCardCount:(NSUInteger)cardCount usingDeck:(Deck*)deck; ошибка говорит, что вы не можете назначить себя вне семьи инициализации. Я понял, в чем проблема. Метод init имел нижний регистр w, и он должен был быть капиталом, поэтому теперь он работает. Это код, который у меня есть для моего инициализатора удобства.

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

Теперь это имеет смысл. Я вызвал назначенный init, который вызывает super, а затем я установил переменную cardMatchMode.

Насколько я понимаю, существует множество объектов, у которых есть инициализатор удобства с дополнительными параметрами, и он просто вызовет назначенный init. Если вы посмотрите на NSString и у него разные инициализаторы с разными параметрами. Вероятно, это вызов init, который является назначенным инициализатором. Это верно?

+0

Вы слышали о конструкторе перегрузкой? Обозначенный инициализатор подобен тому, что в Java как реальный конструктор, который принимает большинство параметров. Затем 'удобный инициализатор' будет вызывать' назначенный инициализатор' для выполнения работы, т. Е. Вызывать 'super init'. –

ответ

6

Согласно Apple, документации, назначенный initalizer

, как правило, INIT ...метод, который имеет большинство параметров и выполняет большую часть работы по инициализации.

Так что в вашем случае это будет - (id)initwithCardCount:(NSUInteger)cardCount usingDeck:(Deck *)deck cardMatchMode:(NSUInteger)matchMode. Все остальные инициализаторы будут иметь меньше аргументов, заполняя недостающие параметры на назначенном инициализаторе с дефолтными или иначе выведенными значениями.

Таким образом, каждый инициализатор удобства вызывает назначенный инициализатор вместо инициализатора суперкласса.

Удобство отведенном инициализатор пара будет выглядеть, как это в вашем случае:

/** 
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

Спасибо за ответ. Ознакомьтесь с моим обновленным ответом. В этом случае я фактически не хочу, чтобы люди вызывали init, потому что я хочу убедиться, что они передают параметры при инициализации этого класса. Не будет параметров по умолчанию. В конечном счете, я думаю, что не имеет значения, сколько параметров назначенные и удобные инициализации имеют столько, сколько указано, вызовет супер и удобство вызовет назначенный. – Yan

15

Назначенный инициализатор - это тот, который вызывает назначенный инициализатор суперкласса своего класса, поэтому он является единственным инициализатором, который вызывает метод на объекте super. Никакой другой инициализатор в классе не должен делать этого; эти вторичные инициализаторы должны вызывать назначенный инициализатор с использованием self. Обычно назначенный инициализатор имеет все параметры, необходимые для создания полезного объекта класса.

Короче говоря, назначенный инициализатор является единственным, который вызывает инициализатор на super, а все остальные инициализаторы в классе вызывают назначенный инициализатор (используя self).

+0

Спасибо за ответ. Я обновил, что имеет больше смысла. Как я понимаю, пока только назначенный инициализатор вызывает супер, а вторичный просто вызывает назначенный init, который должен работать. Все свойства класса будут инициализированы вызовом, обозначенным первым, а затем установкой остальной части вторичного. – Yan

Смежные вопросы