2013-12-07 2 views
1

Я изо всех сил пытался найти правильный и ясный ответ, поэтому я решил задать его здесь.Как запретить наследование метода init?

Я создаю класс А и определить метод инициализации там:

@interface A : NSObject 

- (id)initWithHealth:(int)hp; 

@end 

Тогда я создаю класс B, который наследуется от класса А и определить другой метод инициализации есть:

@interface B : A 

- (id)initWithHealth:(int)hp andDamage:(int)dmg; 

@end 

В основном, когда я собираюсь создать экземпляр объекта из класса B, я буду предлагать Xcode использовать либо - (id) initWithHealth: (int) hp; OR - (id) initWithHealth: (int) hp andDamage: (int) dmg; метод init. Как я могу запретить классу B наследовать метод init из класса A? Я хочу, чтобы мой класс B имел только один метод init, который я определяю. Есть ли способ достичь этого?

Заранее благодарен.

+2

Нет, но вы можете отключить метод A в классе B: http://stackoverflow.com/a/5772821/412916 – Jano

ответ

0

редактируется (благодаря Sulthan и rmaddy)

OK Я нашел ответ на мой вопрос, я должен использовать категории. Но спасибо всем, кто участвовал.

+0

Это не ключевое слово. – Sulthan

+0

Что такое '@ categories'? В Objective-C такой синтаксис не существует. – rmaddy

+0

Да, извините, я имел в виду просто использование категорий, таких как @interface Blah (Category) – Soberman

3

У вас есть несколько вариантов:

Вариант 1 - поставка по умолчанию «ущерб» со старым init методом. В классе B вы бы добавить:

- (id)initWithHealth:(int)hp { 
    return [self initWithHealth:hp andDamage:0]; // use an appropriate default 
} 

- (id)initWithHealth:(int)hp andDamage:(int)dmg { 
    self = [super initWithHealth:hp]; 
    if (self) { 
     // do stuff with dmg 


    return self; 
} 

Вариант 2 - приводит к ошибке во время выполнения, если используется старый init метод. В классе B вы бы добавить:

- (id)initWithHealth:(int)hp { 
    NSAssert(0, @"Dont use this"); 

    return nil; // make compiler happy 
} 

Лично я думаю, что вариант 1 является лучшим выбором.

+0

+1 Правильный ответ IMO, вызывает назначенный инициализатор в суперклассе и переопределяет суперклассификатор класса в подклассе как в соответствии с правилами Apple. Я бы не использовал NSASssert в варианте 2, я бы явно выбрал исключение. – JeremyP

0

В вашем подклассе B вы можете явно определить метод таким образом, чтобы класс не отвечал на него во время выполнения.

- (instancetype) initWithHealth:(int) hp { 
    [self release]; 
    [super doesNotRecognizeSelector:_cmd]; 
    return nil; 
} 

Это очень условна, я видел, как это используется на многих проектах с открытым исходным кодом и на некоторых из проектов моего клиента. Я думаю, что это предпочтительнее для решения @ rmaddy, если вы хотите, чтобы унаследованный метод НИКОГДА не вызывался. Если вы хотите назначить нормальное значение по умолчанию при вызове метода наследуемого init, то другой код работает нормально.

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