Невозможно использовать закрытые методы в подклассе NSObject.
Я создал подкласс NSObject
для использования в качестве модели.
В рамках этого у меня есть несколько открытых методов, которые доступны за пределами этого.
В файле реализации у меня также есть несколько частных методов, таких как:
+(void)publicMethod {
// I am public
}
-(void)privateMethod {
// I am private
}
Однако я не могу вызвать приватный метод из публичного метода. Т.е. не работает следующее:
[self privateMethod];
Это ожидаемое поведение? Должны ли все методы моего подкласса NSObject (используемые в качестве модели) быть открытыми?
2 ответа
Изменить: Обратите внимание, что этот ответ не является полным. Вопрос касается методов экземпляра, вызывающих методы класса, которые я не уловил, когда писал ответ. Но хотя он и не отвечает на этот вопрос, он все же является примером того, как имитировать использование публичных и приватных методов в Objective-C.
В Objective-C нет такой вещи как публичные и приватные методы, но вы можете "спрятать" методы экземпляра, не помещая их в публичный заголовочный файл.
Так Apple делает это. NSObject, UIView, NSString и т. Д. Имеет множество "частных" методов. При этом они не являются частными. Они просто не отображаются в заголовочном файле, который вы включаете в свое приложение.
Если у вашего класса есть экземпляр или метод класса, который невидим для внешнего мира, вы все равно можете просто объявить его самостоятельно - если вы знаете прототип - в своем коде и затем получить к ним доступ.
Я делаю это, создавая два заголовочных файла. Один для публичных методов и один для частных. Допустим, это публичная библиотека, я буду включать только заголовочные файлы с "публичными" методами, которые могут использовать другие разработчики.
С другой стороны, внутри моего проекта я могу включить заголовок "private", который содержит как private, так и public методы, и у меня есть доступ ко всему, что мне нужно.
Примером этого класса являются методы: foo
а также bar
, foo
является публичным и bar
это личное.
"Публичный" заголовок - который называется MyCustomClass.h
будет выглядеть так:
@interface MyCustomClass
- (void)foo;
@end
Затем я создаю расширение класса в другом заголовочном файле, который называется MyCustomClass+Private.h
и это выглядит так. Это также хорошее место для размещения переменных вашего экземпляра, чтобы они тоже не подвергались воздействию "внешнего мира".
@import "MyPublicClass.h"
@interface MyPublicClass () {
NSInteger _myIvar;
}
- (void)bar;
@end
Теперь в реализации класса - который называется MyCustomClass.m
Я все реализую. Обратите внимание, что я включаю частный заголовочный файл.
@import "MyPublicClass+Private.h"
@implementation MyPublicClass
- (void)bar { /* Private Method */
/* Do something */
}
- (void)foo {
[self bar];
}
@end
Решение
Теперь, когда я делаю подкласс MyCustomClass, я в первую очередь также создаю закрытый заголовок для этого класса, который импортирует закрытый заголовок своего суперкласса. Открытый заголовок подкласса импортирует только открытый заголовок суперкласса.
Таким образом, оба foo
а также bar
подвержены подклассам, но не посторонним - как вы бы не поместили ваши частные заголовки в вашу библиотеку - если это то, что вы делаете.
Замечание на вашем примере
В старые времена вы могли делать то, что делаете, и получать предупреждения компилятора. Но в наши дни ARC не устраивает и выдает ошибку компилятора. Это связано с тем, что ARC необходимо знать тип возвращаемого значения, чтобы он мог выпускать / сохранять его, чтобы правильно управлять памятью вашего приложения.
Более простое решение
Более простым способом сделать это также может быть простое добавление расширения суперкласса - с прототипами "частного" метода суперкласса - в реализацию вашего подкласса. Но у этого недостатка есть необходимость проходить через все места, где вы добавляете расширение, если вы измените поведение своего суперкласса в будущем. Так что я бы не рекомендовал это.
окончательный
Надеюсь, что это проясняет и помогает вам. Удачи!
Ваш publicMethod
это метод класса. Так self
это класс в этом методе, а не экземпляр. И класс не реализует privateMethod
потому что это метод экземпляра.