Точка."( ") оператор и Стрелка ( "- > " ) использование оператора в C против Objective-C


Я пытаюсь обернуть голову вокруг некоторых различий в использовании и синтаксисе в 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

Цель-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 тот же в обеих программах (т. е. это указатель на объект доли или struct), почему они используют другой синтаксис при доступе к свойствам? В частности, в C, the numerator доступ к свойству осуществляется с помощью frac->numerator, но с Objective-C, он доступен с помощью оператора dot, с frac.numerator. Так как frac указатель в обеих программах, почему эти выражения разные? Может кто-нибудь помочь прояснить это для меня?

5 57

5 ответов:

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

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

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

точечная нотация-это выбор дизайна. Поскольку мы всегда имеем дело с указателями на экземпляры objc, я бы предположил, что дизайнеры хотели что-то знакомое, что также не нарушало бы существующие программы. Он был представлен в 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 для доступа к указателю на элементы объекта (если они видны).

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

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

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

myObjCVar.prop == [myObjCVar prop];

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

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

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

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