Objective-C Частная дилемма

Я знаю, что Objective-C не поддерживает реальные частные методы. То, что я сейчас делаю для объявления методов 'private', добавляет следующее в класс .m файлов:

@interface MyClass() 

- (void) privateMethodName;

@end


Проблема:

Если я теперь добавлю подкласс и хочу использовать этот метод 'private', я не могу! Я получаю сообщение об ошибке:

Тип получателя "SubClassName" для сообщения экземпляра не объявляет метод с selector 'privateMethodName'


Итак, если я не хочу, чтобы не-подклассы имели доступ к этому методу, но хотите, чтобы подклассы могли это делать, что я могу сделать? Каков наилучший/правильный способ достижения моей цели?

Ответ 1

Вы можете отделить "защищенный" интерфейс от общедоступного. В основном заголовке просто объявите общедоступные методы:

MyMagicThingy.h:

@interface MyMagicThingy: NSObject

- (void) publicMethod;

@end 

Затем добавьте дополнительный заголовок с защищенными методами:

MyMagicThingy+Protected.h:

#import "MyMagicThingy.h"

@interface MyMagicThingy (Protected)

- (void) protectedMethods;

@end

У вас не может быть "реальных" частных/защищенных/общедоступных методов в Objective C (как в: компилятор будет применять правила доступа. Все методы общедоступны). Вы должны пойти с соглашением.

Ответ 2

То, что вы описываете, действительно является защищенным методом. Один из способов преодоления этого: Ivars можно объявить @public, @protected или @private. Вы можете объявить защищенный вспомогательный экземпляр для ограничения доступа к производным экземплярам, ​​который затем перезванивает объект, который его удерживает.

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

Иногда вам просто нужно документировать "не делайте этого, если вы не являетесь подклассом", потому что он не является частью языка. В этом мышлении отдельный заголовок, объявляющий категорию защищенных методов, является одним из моих любимых. Он довольно хорошо скрыт от клиентов, но может быть видимым для подклассов путем явного включения - Dirk представил пример этого в то же время, проверьте его.

Наконец, если вам нравится ObjС++, С++ предлагает этот элемент управления, поэтому вы можете свободно перемещать режимы и видимость.

Ответ 3

Прежде всего

Вы не можете заставить кого-либо не отвечать на любой метод, реализованный на объекте в Objective-C (по крайней мере, не без горения через несколько десятков бритв, что делает Якс менее защищенным от атмосферных воздействий).

Просто не вызывать методы, которые не объявлены в общедоступных файлах заголовков, как соглашение (это то, что вы уже делаете).

Второй

Слово public в приведенном выше параграфе делает трюк:

В Objective-C (по крайней мере, в его текущем воплощении) интерфейс класса можно определить по любому количеству файлов заголовков, используя технику, которую вы только что описали в своем сообщении: Продолжения классов.

Один из таких примеров класса инфраструктуры Apple, который делает это, будет UIGestureRecognizer с его отдельным заголовком подкласса UIGestureRecognizerSubclass.h.


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