Подклассы ВСЕГДА должны реализовывать назначенный инициализатор в Objective-C? - PullRequest
1 голос
/ 19 января 2011

Должны ли подклассы, которым не нужно добавлять код инициализации для конкретного класса, реализовывать назначенный инициализатор суперкласса?

Документация Apple по методу init NSObject содержит некоторые обсуждения:

"Каждый класс должен гарантировать, что Метод init либо возвращает полностью функциональный экземпляр класса или выдвигает исключение Подклассы должны переопределить метод init, чтобы добавить специфический для класса код инициализации. "

"Если подкласс выполняет какую-либо инициализацию сам по себе, он должен определить свой собственный назначенный инициализатор. Этот метод следует начать с отправки сообщения супер, чтобы призвать назначенный инициализатор его суперкласса. "

Однако ничего не указано для случая, когда подкласс не нуждается в дополнительном коде инициализации.

Приведенный ниже код пытается прояснить мой вопрос. ClassA имеет назначенный инициализатор с именем initWithX: Y: . ClassB не требуется дополнительная инициализация, все обеспечивается ClassA.

Пояснительный код:

@interface ClassA : NSObject {
  NSInteger x;
  NSInteger y;
}

- (id)initWithX:(NSInteger)initX Y:(NSInteger)initY;

@end

@implementation ClassA 

- (id)initWithX:(NSInteger)initX Y:(NSInteger)initY {
  if(self = [super init]) {
    x = initX;
    y = initY;
  }
  return self;
}
@end

@interface ClassB : ClassA {
  //no extra variables
} 

//some extra static methods add to provide some differences 
//  between ClassA and ClassB in sample code
+ (NSInteger)extraMethodOne;
+ (NSInteger)extraMethodTwoWithInteger:(NSInteger)anInteger;

@end

@implementation ClassB

/////////////??QUESTION HERE??///////////////////
//Is the implementation below needed?
//If I call [[ClassB alloc] initWithX:1 Y:2], won't it run the code in ClassA
//  with the self set to whatever [ClassB alloc] is?
/////////////////////////////////////////////////
- (id)initWithX:(NSInteger)initX Y:(NSInteger)initY {
  if(self = [super initWithX:initX Y:initY]) {
    /* Don't need class-specific initialization code */
  }
}

//some extra static methods add to provide some differences 
//  between ClassA and ClassB in sample code
+ (int)extraMethodOne {return 1;}
+ (int)extraMethodTwoWithInteger:(NSInteger)anInteger {return 2 + anInteger;}

@end

Ответы [ 3 ]

3 голосов
/ 19 января 2011

"Однако ничего не указано для случая, когда подкласс не нуждается в дополнительном коде инициализации."

Это правильно - ничего не делать.

Когда Apple говорит "" Если , то подкласс выполняет какую-либо инициализацию своей собственной ... бла-бла "что они означают" Если и только если подкласс выполняет любую собственную инициализацию ... бла-бла ... в противном случае вообще ничего не делает . "

Стоит помнить, что : не очень часто вы создаете целый массивный подкласс, который имеет целую цепочку собственных инициализаторов (назначенный инициализатор и многое другое), а затем вы (или другие) будут создавать подклассы этого нового подкласса. (Если это правда, что вы или другие люди будете создавать подклассы этого нового подкласса, тогда, да, именно тогда вы должны были быть осторожны, чтобы делать то, что Apple говорит выше.)

На практике в 99% случаев вы просто подклассифицируете UIView, и вы помещаете некоторый код в инфраструктуру «init», которую XCode автоматически вставляет для вас. Если, что невероятно, кто-то затем подклассит наш подкласс там, ему придется выяснить, что, подождите, «init» - это назначенный инициализатор в вашем подклассе!

Относительно Apple doco. Они делают потрясающую работу, но есть много примеров этого вида проблемы в доко. Хороший пример: Есть ли правильный способ обработки перекрывающихся братьев и сестер NSView? . Обратите внимание на часть, которая говорит "бессмысленный"

0 голосов
/ 19 января 2011

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

0 голосов
/ 19 января 2011

Ответ на ваш вопрос:

"Если подкласс выполняет какую-либо собственную инициализацию, он должен определить свой собственный назначенный инициализатор. Этот метод должен начинаться с отправки сообщения super, чтобы вызвать назначенный инициализатор его суперкласса."

Если вам не нужно выполнять дополнительную инициализацию, нет необходимости переопределять (или создавать свой собственный) указанный инициализатор. Поиск метода для initWithX:Y: будет просто использовать реализацию суперкласса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...