Точка."( ") оператор и Стрелка ( "- > " ) использование оператора в 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 ответов:
frac
на самом деле не то же самое в обеих программах.С
Fraction
этоstruct
, который является базовым типом без перегруженных операторов и только действительно может быть построен и разрушен по умолчанию. Если вы определяете функции или поля в структуре, способ доступа к этим свойствам вC
С точкой (.
оператор). Objective-C поддерживает этот оператор при использованииstruct
s. для удобства можно выполнить операцию разыменования и точки с помощью стрелка (->
оператора) (два эквивалентных выражения, которые вы упоминаете). 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]->
а затем вывести список завершения метода, вы видите это:здесь вы можете увидеть кучу нормальных полей, к которым мы обычно обращаемся с синтаксисом квадратных скобок (например,
[[UIApplication sharedApplication] delegate]
). Эти элементы, однако,C
поля, в которых хранятся значения соответствующих свойств Objective-C.Итак, вы можете примерно думать об этом так:
точка оператор на объекте C
- (во время выполнения) возвращаемое значение поля
оператор стрелки на объекте C (указатель)
- разыменования указателя
- возвращаемое значение поля
оператор точки / квадратные скобки на объекте Objective-C (указатель)
- (во время компиляции) заменить вызов
objc_msgSend
- (как запустить время) посмотрите определение класса Obj-C, бросьте исключение, если что-то пошло не так
- разыменования указателя
- возвращаемое значение поля
оператор стрелки на объекте Objective-C (указатель)
- (во время выполнения) разыменования указателя
- возвращаемое значение поля
теперь я определенно упрощаю здесь, но подводя итог: операторы стрелки, похоже, делают в основном то же самое в обоих случаях, но оператор точки имеет дополнительное / другое значение в 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 одинаковы.