Точка (".") Оператор и стрелка ("->") оператор использования в C против Objective-C - PullRequest
61 голосов
/ 31 января 2012

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

C Код:

// declare a pointer to a Fraction
struct Fraction *frac;

...

// reference an 'instance' variable
int n = (*frac).numerator;     // these two expressions
int n = frac->numerator;       // are equivalent

Код Objective-C:

// declare a pointer to a Fraction
Fraction *frac = [[Fraction alloc] init];

...

// reference an instance variable
int n = frac.numerator;        // why isn't this (*frac).numerator or frac->numerator??

Итак, видя, как frac одинаково в обеих программах (то есть это указатель на объект или структуру Fraction), почему они используют различный синтаксис при доступе к свойствам?В частности, в C к свойству numerator обращаются с помощью frac->numerator, но с Objective-C к нему обращаются с помощью оператора точки с frac.numerator.Поскольку frac является указателем в обеих программах, почему эти выражения отличаются?Кто-нибудь может помочь уточнить это для меня?

Ответы [ 5 ]

77 голосов
/ 31 января 2012

frac на самом деле не то же самое в обеих программах.

C Fraction - это struct, который является базовым типом без перегруженных операторов и только реально может быть создан и уничтожен по умолчанию. Если вы определяете функции или поля в структуре, доступ к этим свойствам в C осуществляется с помощью оператора точки (.). Objective-C поддерживает этот оператор, когда вы используете struct s. Для удобства вы можете выполнить операцию разыменования и точки, используя оператор стрелки (->) (два упомянутых вами эквивалентных выражения). Objective-C также сохраняет это при доступе к struct s.

Objective-C Fraction в вашем примере, однако, вероятно (можно предположить) указатель по крайней мере типа id, который является просто именем класса и указателем на экземпляр этого класса под капотом. Также очень вероятно, что это будет подкласс NSObject или NSProxy. Эти классы Objective-C отличаются тем, что имеют целый слой предопределенных операций поверх просто структуры C (если вы действительно хотите в нее углубиться, вы можете взглянуть на Objective-C Runtime Ссылка ). Также важно отметить, что класс Objective-C всегда является указателем .

Одной из самых основных операций является objc_msgSend. Когда мы оперируем этими типами объектов, компилятор Objective C интерпретирует оператор точки (.) или синтаксис в квадратных скобках ([object method]) как вызов метода objc_msgSend. Для получения более подробной информации о том, что на самом деле происходит здесь, см. эту серию публикаций Билла Бумгарнера, инженера Apple, который курирует разработку среды выполнения Obj-C.

Оператор стрелки (->) не должен использоваться на объектах Objective-C. Как я уже говорил, экземпляры класса Objective-C - это структура C с добавленным дополнительным уровнем связи, но этот уровень связи по существу обходится при использовании стрелки. Например, если вы откроете Xcode и наберете [UIApplication sharedApplication]->, а затем откроете список завершения метода, вы увидите следующее:

A list of internal ivars on an Obj-C object when using the arrow operator

Здесь вы можете увидеть группу нормальных полей, к которым мы обычно обращаемся с помощью синтаксиса в квадратных скобках (например, [[UIApplication sharedApplication] delegate]). Эти конкретные элементы, однако, являются полями C, в которых хранятся значения их соответствующих свойств Objective-C.

Итак, вы можете приблизительно представить это так:

Оператор точки на объекте C

  1. (во время выполнения) Возвращаемое значение поля

Оператор стрелки на объекте C (указатель)

  1. Указатель разыменования
  2. Возвращаемое значение поля

Оператор точки / квадратные скобки на объекте Objective-C (указатель)

  1. (во время компиляции) Заменить на вызов objc_msgSend
  2. (во время выполнения) Посмотрите определение класса Obj-C, выведите исключение, если что-то пошло не так
  3. Указатель разыменования
  4. Возвращаемое значение поля

Оператор стрелки на объекте Objective C (указатель)

  1. (во время выполнения) Указатель разыменования
  2. Возвращаемое значение поля

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

9 голосов
/ 31 января 2012

Точечная нотация - это выбор дизайна. Поскольку мы всегда имеем дело с указателями на экземпляры объектов, я бы предположил, что дизайнеры хотели чего-то знакомого, что также не сломало бы существующие программы. Он был представлен в ObjC 2 - всего несколько лет назад. До этого вам всегда приходилось использовать скобки для обмена сообщениями.

Точечная запись имеет значение, хотя - это не прямой доступ, а сообщение .

То есть:

obj.property = val;
// is the same as:
[obj setProperty:val];
// and not:
obj->property = val;


val = obj.property;
// is the same as:
val = [obj property];
// and not:
val = obj->property;

Вы все еще можете написать obj->ivar для доступа к указателю на члены объекта (если он виден).

6 голосов
/ 31 января 2012

В вашем первом примере Fraction - это структура.Во втором примере Fraction - это класс Objective-C (а в iOS, скорее всего, подкласс NSObject).

C ++ не допускает перегрузку operator .,Следовательно, без дополнительной информации вы можете сделать вывод, что точка, которую вы видите, является дополнительной языковой конструкцией, интегрированной в Objective-C, а не определенным или перегруженным оператором C / C ++.

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

myObjCVar.prop == [myObjCVar prop];
2 голосов
/ 31 января 2012

Оператор точки на объектах - это специальный синтаксис для доступа к свойствам объектов.Он вызывает геттер или сеттер свойства за кулисами.Так, например, [@"hello" length] и @"hello".length эквивалентны *.Для всех других типов точка совпадает с точкой C, а стрелка всегда одинакова.

* Примечание. Метод доступа не всегда будет называться так же, как свойство.Если это объявленное свойство и в объявлении указан специальный метод get или setter, то вместо него будет использоваться тот.

1 голос
/ 31 января 2012

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

Точечная запись, используемая для объектов в Objective-C, используется для свойств, которые были введены в Objective-C2,0.Однако в случае структур -> и точка обозначения между Objective-C и C одинаковы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...