Создает ли private @property переменную экземпляра @private?

Я прочитал, что @synthesize автоматически создаст соответствующие переменные экземпляра для @property и что @protected по умолчанию защищены @protected . Но что, если я использую расширение classа (например, ниже), чтобы указать, что методы @property должны быть частными?

 // Photo.m @interface Photo () @property (nonatomic, retain) NSMutableData *urlData; @end 

Будет ли соответствующий ivar быть @private ? Или я должен явно объявить его как @private так?

 // Photo.h @interface Photo : Resource { @private NSMutableData *urlData; } 

переменные экземпляра @private – это функция времени компиляции. Учитывая, что поддерживающие ivars для @property уже скрыты, @private ничего не делает. По сути, это уже @private .

Разрабатывая ответ Кевина:

Когда вы объявляете class, например:

 @interface SomeClass : NSObject { @public id publicIvar; @protected id protectedIvar; @private id privateIvar; } @end 

компилятор 1 принимает решение о макете экземпляра для этого classа. Этот макет определяет смещения переменных экземпляра в отношении адреса экземпляров этого classа. Один из возможных вариантов:

  +--> publicIvar address = instance address + offsetOfPublicIvar | | +-----+------------+-----+---------------+-----+-------------+-----+ | ... | publicIvar | ... | protectedIvar | ... | privateIvar | ... | +-----+------------+-----+---------------+-----+-------------+-----+ | | +--> instance address 

Когда переменная экземпляра ссылается в коде – либо в реализации classа, либо в какой-либо другой части базы кода, компилятор заменяет эту ссылку соответствующим смещением переменной экземпляра в отношении адреса соответствующего экземпляра.

Например, при реализации SomeClass,

 privateIvar = someObject; 

или

 self->privateIvar = someValue; 

переводится как нечто вроде:

 *(self + offsetOfPrivateIvar) = someObject; 

Аналогично, вне classа,

 SomeClass *obj = [SomeClass new]; obj->publicIvar = someObject; 

переводится как нечто вроде:

 SomeClass *obj = [SomeClass new]; *(obj + offsetOfPublicIvar) = someObject; 

Однако компилятор разрешает это только в соответствии с видимостью переменной экземпляра:

  • Частную переменную экземпляра можно ссылать только на реализацию соответствующего classа;
  • Защищенная переменная экземпляра может ссылаться только на реализацию соответствующего classа и его подclassов;
  • На переменную открытого экземпляра можно ссылаться где угодно.

Когда переменная экземпляра объявляется в расширении classа, например

 @interface SomeClass () { id extensionIvar; } @end 

компилятор добавляет его в макет переменной экземпляра:

 +-----+------------+-----+---------------+ | ... | otherIvars | ... | extensionIvar | +-----+------------+-----+---------------+ 

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

С другой стороны, переменная расширения известна только исходному файлу, где она была объявлена. Таким образом, мы можем сказать, что переменные экземпляра, объявленные в расширениях classов, скрыты от других файлов. Те же рассуждения применимы к резервным переменным экземпляра свойств, объявленных в расширениях classов. Он похож на @private , но более ограничительный.

Обратите внимание, однако, что во время выполнения правила видимости не применяются. Используя кодирование с ключом, иногда может использоваться произвольный исходный файл (здесь описываются правила), доступ к переменной экземпляра:

 SomeClass *obj = [SomeClass new]; id privateValue = [obj valueForKey:@"privateIvar"]; 

включая переменную экземпляра, объявленную в расширении:

 id extensionValue = [obj valueForKey:@"extensionIvar"]; 

Независимо от KVC доступ к переменным экземпляра осуществляется через API-интерфейс Objective-C:

 Ivar privateIvar = class_getInstanceVariable([SomeClass class], "privateIvar"); Ivar extensionIvar = class_getInstanceVariable([SomeClass class], "extensionIvar"); id privateValue = object_getIvar(obj, privateIvar); id extensionValue = object_getIvar(obj, extensionIvar); 

Обратите внимание, что class может иметь более одного расширения classа. Однако одно расширение classа не может объявлять переменную экземпляра с тем же именем, что и другая переменная экземпляра, включая переменные экземпляра, объявленные в других расширениях classов. Поскольку компилятор генерирует такие символы, как:

 _OBJC_IVAR_$_SomeClass.extensionIvar 

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

1 Этот макет можно изменить с помощью среды выполнения Objective-C. Фактически, смещения вычисляются компилятором и сохраняются как переменные, и среда выполнения может изменять их по мере необходимости.

PS: Не все в этом ответе применимо ко всем версиям компилятора / исполнения. Я только рассмотрел Objective-C 2.0 с не-хрупкими ABI и недавними версиями Clang / LLVM.

  • Доступ к файлам свойств программно с помощью Spring?
  • Почему нам нужны свойства в C #
  • В чем разница между инкапсулированием частного члена как свойства и определением свойства без частного члена?
  • Как реализовать виртуальные статические свойства?
  • Json.NET (Newtonsoft.Json) - Два «свойства» с таким же именем?
  • Как пропустить Получить только свойства в servicestack json serializer?
  • В чем разница между свойством зависимостей и прикрепленным свойством в WPF?
  • C # настройка / получение свойств classа по имени строки
  • Свойства Java Backslash
  • Должен ли доступ к переменной внутри одного classа через свойство?
  • Загрузить файл свойств в JAR?
  • Interesting Posts

    Как уменьшить потребление памяти PdfPTable со многими ячейками

    Каков наилучший способ реализовать «запомнить меня» для веб-сайта?

    Создание и создание раздела с использованием сценария bash

    Переход с IE9 на IE8 на Windows 7

    css width: calc (100% -100px); альтернатива с использованием jquery

    Мой ноутбук подключен, зарядка, но мощность не увеличивается

    сервер rails не запускается с mysql2, используя rvm & ruby ​​1.9.2-p0 на OSX 10.6.5

    Каково значение по умолчанию «Результат» в Delphi?

    Поддержка локальной базы данных Sql для телефона Windows 7

    Как можно добавить разделительную линию в Android RecyclerView?

    Что такое семантика copy-on-modify в R, а где канонический источник?

    Самый простой способ инициализировать std :: vector с жестко закодированными элементами?

    интернационализация в JSF с записями ResourceBundle, которые загружаются из базы данных

    Как создать ярлык на рабочем столе для приложения Windows 8 Modern UI?

    32-разрядная ОС, процессор на базе x64 в Windows 8.1

    Давайте будем гением компьютера.