Подтвердить что ты не робот

Как создать реальную переменную частного экземпляра?

Я хочу создать переменную экземпляра, к которой нельзя получить доступ извне. Возможно ли это в objective-c? Я помню, что у Apple есть частные переменные и тому подобное, но если люди знают о них, они могут их использовать. Apple называет этот "частный API", но, очевидно, другие могут получить доступ к этому материалу, если узнают, что там.

До сих пор я считал, что что-то вроде этого создает частную переменную экземпляра:

@interface MyClass : NSObject {
    CGFloat weight;
}

Нет @property, нет @synthesize, только объявление выше.

Также я знаю, что Apple добавляет _inFrontOfTheirPrivateInstanceVariables, но они сказали где-то, что им не нравится, когда другие делают это, потому что они могут переопределить случайно скрытые переменные экземпляра при этом.

Какой трюк здесь?

4b9b3361

Ответ 1

Вы можете использовать ключевое слово @private внутри {}, чтобы сделать все последующие объявления переменных частными. Видимость по умолчанию @protected (что аналогично protected в Java) и, как правило, хорошо работает. Вам нужно будет специально объявить переменную как @public, чтобы она была непосредственно доступна вне класса.

Эта документация Apple содержит дополнительную информацию об области видимости и видимости переменных.

Существует также различие между "частным API" и частными переменными. В Objective-C вы не можете использовать методы private - любой может вызвать любой метод. Существует несколько способов создания "секретных" методов, но это несколько выходит за рамки этого вопроса. Вот несколько связанных вопросов SO:

Что касается ведущего _ перед переменными, имейте в виду, что Apple также резервирует этот префикс для методов "private". Лучший способ гарантировать, что вы избегаете проблем, - использовать обычные соглашения об именах для собственных переменных и методов. Однако, если вы не подклассируете что-то из Cocoa (кроме NSObject), вы можете быть достаточно уверены, что не столкнетесь с проблемами.

Ответ 2

С новым компилятором LLVM, доступным в XCode 4 и более поздних версиях, вы можете объявить переменные @private в категориях по умолчанию внутри вашего файла реализации (.m):

@interface ClassName()
{
@private
// private variables here
}
@end

@implementation ClassName
// you can use private variables here
@end

Я считаю это удобным, так как я ненавижу, что частные переменные загрязнения вносят в мои файлы заголовков.

Ответ 3

Вы можете определить частные методы, просто используя их только в @implementation, а не в @interface.

Аналогично, вы можете определить переменные частного экземпляра внутри анонимного блока в начале @implementation - как и для общедоступных ivars внутри @interface.

См. следующий пример.

@interface EXClass : NSObject
{
uint8_t publicInteger;
float publicFloat;
}

-(void)publicMethod;
@end

@implementation EXClass
{
uint8_t privateInteger;
float privatefloat;
}

-(BOOL)privateMethod {
return FALSE;
}

Помните, что методы objective-C отправляются как сообщения во время выполнения, хотя (вместо привязки времени компиляции С++), поэтому responsesToSelector: все равно вернет true и выполнит выбор: все равно вызовет метод. Иварцы будут полностью закрыты.

Если вы создавали библиотеку, теоретически никто не знал бы о каких-либо методах, которые вы не объявляли в файлах заголовков.

Ответ 4

Все iVars в Objective-C защищены по умолчанию. Если вы не пишете методы доступа, чем другие классы, они не смогут видеть переменные.

Два исключения - это категории и подклассы.

Ответ 5

Документы Apple для именования переменных экземпляра не содержат явного предупреждения против использования подчеркивания в имени переменных экземпляра, таких как документы частного метода.

Имена переменных экземпляра и типов данных

Я также помню, что разговор между Вил Шипли и несколькими другими разработчиками OS X касается подчеркивания. Из-за того, как работает компилятор Obj-C, если Apple должна была добавить новую переменную экземпляра в класс в своих рамках, это заставит все приложения, использующие эти фреймворки, перекомпилировать. Что касается ранее существовавших переменных экземпляра, вы должны получить предупреждение, когда вы нажмете на него.

Ответ 6

Я видел следующее использование в примере приложения (PaintGL) от Apple

В .m файле

@interface MyClass (private)
  - (void) privateMethod();
  @property(...) myProperty;
@end

Отказ от ответственности: пример приложения имеет только объявления методов, я видел объявление частной собственности в этом потоке SO

Ответ 7

Вы можете не создать реальную переменную частного экземпляра. Objective-C - динамический язык, и поэтому можно получить доступ к любой переменной (даже @private).

Мой лучший подход:

Используйте его в блоке реализации вашего файла .m. Тогда это не видно и блокирует KVC, так что KVC не будет работать

@implementation ClassName {
    // default to @protected
    // but the subclasses can't see ivars created in the implementation block
    float number;
}

+ (BOOL)accessInstanceVariablesDirectly {
    return NO; // no KVC
}

@end