Невозможно использовать закрытые методы в подклассе 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 потому что это метод экземпляра.

Другие вопросы по тегам