В чем разница между синтаксисом точек и синтаксисом в квадратных скобках? - PullRequest
14 голосов
/ 15 сентября 2011

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

  1. Есть ли принципиальная разница в отправке сообщений и вызове методов?Objective-C позволяет мне делать оба: object.message дает тот же результат, что и [object message].Я думаю, может быть, вложенные сообщения не могут быть созданы с использованием стратегии точечного оператора?

  2. Я создал объект NSArray, теперь я собираюсь напечатать результаты для этого, используя NSEnumerator:

    id myObject = [object objectEnumerator];

    в цикле while, итерации и печати результатов. тип из myObject равен id, что означает, что он разрешается во время выполнения, а не во время компиляции.Я очень четко знаю, какие объекты хранятся в моих NSArray - это NSString с, поэтому, изменив тип myObject на NSString * myObject, он работает просто отлично.Тем не менее, я экспериментировал и обнаружил, что myObject может быть любого типа, будь то NSString или NSArray или NSEnumerator, и любая из этих функций прекрасно работает, прекрасно повторяя объект NSArray и получая тот жеРезультаты.Что с этим?

Ответы [ 5 ]

15 голосов
/ 15 сентября 2011

Я не уверен, какое различие вы пытаетесь провести между "отправкой сообщения" и "вызовом метода", поскольку это два способа описания одной и той же вещи.Синтаксис с точкой является просто ярлыком для вызова методов получения и установки, то есть:

[foo length]
foo.length

точно такие же, как и:

[foo setLength:5]
foo.length = 5

Как правило, следует использовать только синтаксис точкикогда вы используете геттеры и сеттеры;используйте синтаксис в квадратных скобках для всех остальных вызовов методов.

Для второго вопроса: как работает динамическая типизация.Любые объявления типов, которые вы помещаете в свой код, являются подсказками для компилятора;Ваши вызовы метода Objective C всегда будут работать, пока объекты отвечают на них.

8 голосов
/ 15 сентября 2011

Это различие, ориентированное на человека, читающего ваш код. Синтаксис точки указывает на состояние (я обращаюсь к ivar), синтаксис метода указывает на поведение (я выполняю некоторые действия). Для времени выполнения оба одинаковы.

Я думаю, что намерение Apple состоит в том, чтобы показать аксессоры как деталь реализации, о которой вам не стоит беспокоиться. Даже когда они могут вызывать побочные эффекты (из-за некоторого дополнительного кода в методе доступа), они обычно этого не делают, поэтому абстракция несовершенна, но она того стоит (ИМХО). Другим недостатком использования точечной нотации является то, что вы не знаете, есть ли за ней структура или объединение (что в отличие от отправки сообщений никогда не вызывает побочных эффектов при назначении). Возможно, Apple следовало использовать что-то отличное от точки. *shrugs*

Я думаю, что вложенные сообщения не могут быть созданы с использованием стратегии точечного оператора?

Точечная запись может использоваться для вложения вызовов, но учтите следующее:

shu.phyl.we.spaj.da
[[[[[shu]phyl]we]spaj]da]

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

2 голосов
/ 15 сентября 2011

1: ваша терминология неверна. Оператор точки - это не «вызов метода», а другая операция. Это просто другой внешний вид для отправки сообщений. Нет разницы между [x y] и x.y. Точечный синтаксис может принимать только один аргумент, поскольку он предназначен для использования только для доступа к свойству.

2: Статический (во время компиляции) тип объекта не влияет на его поведение во время выполнения. Ваш объект по-прежнему является NSEnumerator, даже если вы называете его чем-то другим.

0 голосов
/ 15 сентября 2011
  1. Отправка сообщений является предпочтительным способом сделать это.Это то, что сообщество использует и усиливает концепцию объектов, отправляющих сообщения друг другу, которая вступает в игру позже, когда вы начинаете работать с селекторами и спрашиваете объект, реагирует ли он на селектор (сообщение).*

    id в основном указатель на что-либо.Требуется некоторое привыкание, но это основа того, как Objective-C обрабатывает динамическую типизацию объектов.Когда NSLog() встречает спецификатор формата %@, он отправляет сообщение description объекту, который должен заменить токен (это реализовано в суперклассе NSObject и может быть переопределено в подклассе для получения желаемоговывод).

В будущем, когда вы будете делать это, вам может быть проще сделать что-то вроде этого:

for (NSString *s in YourNSArrayInstance) //assuming they are NSStrings as you described
{
    NSLog(@"%@", s);
}

Или даже просто:

for (NSString *s in YourNSArrayInstance) //assuming they are NSStrings as you described
    NSLog(@"%@", s);

Со временем вы научитесь любить отправку сообщений.

0 голосов
/ 15 сентября 2011

1) Они оба отправляют сообщения, только разный синтаксис. [object message] - это традиционный синтаксис, object.message - это «точечная нотация», но означает то же самое. Вы можете делать некоторые виды вложений с точечной нотацией, но вы не можете ничего делать с методами, которые принимают сложные аргументы. В общем, программисты Obj-C старой руки не используют точечную нотацию, за исключением простых обращений к методам доступа. ИМХО.

2) Время выполнения действительно умное и может понять это на лету. Приведение типов указателей на самом деле просто подсказка компилятору, чтобы вы знали, когда вы все испортили. Это ничего не значит (в данном случае), когда сообщение отправляется в массив для получения значения.

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