Как я могу предотвратить неправильное переопределение метода - PullRequest
3 голосов
/ 13 апреля 2011

Как я могу предотвратить переопределение метода в подклассе, пропустив вызов реализации его суперкласса внутри?
Я знаю, что вызов [super methodName]; иногда решит мою проблему.
Но если кто-то еще былиспользовать мой родительский класс и переопределить мой метод, случайно пропущенный при вызове super, что я могу сделать?

Еще несколько объяснений:

Я создаю VC1 viewcontroller, у которого есть метод -(void)indexDidChange:(int)index { }.Я пишу там некоторые действия, которые мне нужно выполнять каждый раз.и я делю на него подкласс этого viewcontroller, названного SVC1, мне нужно -(void)indexDidChange:(int)index { } для выполнения некоторых других действий, но в то же время необходимо выполнить действие VC1 -(void)indexDidChange:(int)index { }.Поэтому мне нужно позвонить, как,

 -(void)indexDidChange:(int)index { 
[super indexDidChange:index];
}

Так что я решил изменить функцию VC1, как,

  -(void)indexDidChange:(int)index {
     [self currentIndexDidChange:(int)index];
 }

-(void)currentIndexDidChange:(int)index { }

И мне нужно - (void) currentIndexDidChange: (int) index {} напереопределить и предотвратить - (void) indexDidChange: (int) index {} от переопределения.

Возможно ли это?

Ответы [ 3 ]

8 голосов
/ 13 апреля 2011

Редактировать: После того, как ОП перефразировал вопрос, становится ясно, что ОП на самом деле НЕ ищет окончательных методов , несмотря на первоначальную формулировку вопросов, которая подразумевала только это.

Новое (обновлено)ответ на вопрос OP о методе, переопределяющем безопасность:

Согласно вашему перефразированному вопросу, вы не ищете способ защиты метода от переопределения вообще, а скорее беспокоитесь о том, что один из ваших подклассов переопределяет метод, и случайно пропускает включениевызов super в его новой реализации.

Это, однако, довольно распространенная и широко распространенная проблема , с которой вы сталкиваетесь ежедневно, не обращая на это большого внимания.

Каждый программист Objective-C знаком со следующим методом, верно?

- (void)dealloc {
    [iVar release], iVar = nil;
    [super dealloc]; //skipping this call to super is fatal!
}

И мы все знаем, что пропуск [super dealloc]; делает вещи неудобными.(afaik clang-компилятор выдает предупреждение, если dealloc не обращается к super, ... довольно удобно.)

Несмотря на то, что неправильное переопределение этого метода может иметь фатальные последствия, Apple не решила ставить какие-либоздесь установлена ​​система безопасности.

Вместо этого Apple сделала это (как это было сделано с любым другим методом, требующим вызовов super):

  • Добавить примечаниек документации метода:

После выполнения освобождения класса для класса метод подкласса должен включать версии dealloc суперкласса через сообщение super

  • Ожидайте, что вы , программист, будете взрослыми и ответственными за то, что вы делаете .И для игры по правилам (как определено в документации).

Имейте в виду, что - (void)dealloc ни в коем случае не является исключением.Есть десятки и десятки методов этого типа в какао.(Возьмите примерно любую производную от - (id)init, большинство методов наблюдения КВО и т. Д., Чтобы назвать несколько.)

Итак, что вы должны сделать:

  1. Напишите хорошую документацию для вашего метода .(лучше для всего вашего проекта , на самом деле)
  2. Добавьте большую громкую заметку к документации вашего метода, объясняя его правила.
  3. Добавьте примечание к каждой из реализаций переопределенных методов вашего подкласса , прямо над строкой, вызывающей super, и попросите читателя / dev искать документацию, если сомневаетесь в правилах.(необязательно)
  4. Код ответственно.В противном случае вам не стоит кодировать в первую очередь. В конечном итоге от этого пострадают ваши клиенты.

Старый (предварительно перефразируя) ответ об архивировании псевдо-финаламетоды:

То, что вы запрашиваете, является эквивалентом final-функции , известной из Java или C ++.В отличие от Java или C ++, в Objective-C нет окончательных методов .

В зависимости от вашей ситуации, есть решения, которые могут приблизить вас, по крайней мере, к тому, что выстремление к . Все, что вы получите, это немного лучшее разделение .Вы не получите от них значительной защиты .В Objective-C вы даже не можете быть уверены в происхождении ваших методов. Метод Swizzling позволяет обменять методы по желанию вводом кода вы даже внедряете код в процессы во время выполнения .Все это разработано в Objective-C.Objective-C позволяет отпилить ветку, на которой вы сидите.Таким образом, он требует, чтобы вы вели себя как взрослый.Таким образом, нет никаких частных методов.Если метод объявлен как приватный, вы, как разработчик, должны вести себя соответствующим образом.

Теперь возможно " solutions ":

Если только ваш суперкласс, если предполагается вызватьданный (окончательный) метод в любом случае:

  1. Тогда Macmade решение из , делающее ваш метод псевдоприватным , будет работать достаточно хорошо.Недостатком сокрытия объявлений метода является то, что вызов скрытого метода из подклассов выдаст вам предупреждение компилятора, в основном не позволяя * (sic!) * Вызвать его.(Это не помешает вам вызывать метод. Однако будет препятствовать вам , только выдавая предупреждения компилятора.)

Если подклассыоднако ожидается, что он вызовет данный (последний) метод:

  1. Используйте шаблон делегирования и тем самым сделайте только те методы, которые разрешены для переопределения, открытыми.
  2. Чтобы вообще предотвратить переопределение, вы можете использовать кластеры и abstract factory шаблоны, которые скрывают ваши классы реализации и, таким образом, полностью предотвращают переопределение.(Apple NSArray, NSDictionary, NSSet классы делают это)

Однако вы можете заметить, что при отсутствии защиты Objective-C обычно можно только выбирать между двумя : открытость, защищенность, не смешивать их .

4 голосов
/ 13 апреля 2011

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

MyClass.m

@interface MyClass( Private )

- ( void )myMethod;

@end

@implementation MyClass( Private )

- ( void )myMethod
{}

@end

@implementation MyClass

/* ... */

@end
0 голосов
/ 13 апреля 2011

Если вы не объявляете свою функцию в ".h файле", значит, ее нет в списке, я думаю.

...