Точечная нотация и обозначение сообщений для объявленных свойств

Теперь у нас есть "точечное" обозначение свойств. Я видел различные назад и далее о достоинствах точка нотации и обозначения сообщений. Чтобы сохранить ответы без изменений, я не буду отвечать в любом случае в вопросе.

Что вы думаете о точечной нотации или нотации сообщений для доступа к свойствам?

Пожалуйста, постарайтесь сфокусироваться на Objective-C - моя одна предвзятость, которую я изложу, заключается в том, что Objective-C - Objective-C, поэтому ваши предпочтения в том, что они похожи на Java или JavaScript, недействительны.

Действительный комментарий связан с техническими проблемами (упорядочение операций, приоритет выбора, производительность и т.д.), ясность (структура и природа объекта, как pro, так и con!), лаконичность и т.д.

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

Ответ 1

Не используйте точку для поведения. Используйте точку, чтобы получить доступ или установить атрибут как материал, обычно атрибуты, объявленные как свойства.

x = foo.name; // good
foo.age = 42; // good

y = x.retain; // bad

k.release; // compiler should warn, but some don't. Oops.

v.lockFocusIfCanDraw; /// ooh... no. bad bad bad

Для новых пользователей, относящихся к Objective-C, я бы рекомендовал не использовать точку для чего-либо, кроме материала, объявленного как @property. Как только вы почувствуете язык, сделайте то, что кажется правильным.

Например, я нахожу следующее совершенно естественным:

k = anArray.count;
for (NSView *v in myView.subviews) { ... };

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

Ответ 2

Позвольте мне начать с того, что я начал программировать в Visual/Real Basic, а затем перешел на Java, поэтому я довольно привык к синтаксису точек. Однако, когда я, наконец, перешел на Objective-C и привык к скобкам, затем увидел введение Objective-C 2.0 и его точечный синтаксис, я понял, что мне это действительно не нравится. (для других языков это нормально, потому что это то, как они катятся).

У меня есть три основных говядины с точечным синтаксисом в Objective-C:

Говядина # 1: Непонятно, почему вы можете получать ошибки. Например, если у меня есть строка:

something.frame.origin.x = 42;

Затем я получу ошибку компилятора, потому что something - это объект, и вы не можете использовать structs объекта как lvalue выражения. Однако, если у меня есть:

something.frame.origin.x = 42;

Тогда это компилируется просто отлично, потому что something является самой структурой, которая имеет член NSRect, и я могу использовать ее как lvalue.

Если бы я принял этот код, мне нужно было потратить некоторое время, пытаясь понять, что такое something. Это структура? Это объект? Однако, когда мы используем синтаксис скобки, он намного яснее:

[something setFrame:newFrame];

В этом случае нет абсолютно никакой двусмысленности, если something является объектом или нет. Внедрение двусмысленности - моя говядина # 1.

Говядина # 2: В C синтаксис точек используется для доступа к членам структур, а не к методам вызова. Программисты могут переопределять методы setFoo: и foo объектов, но все же получать к ним доступ через something.foo. На мой взгляд, когда я вижу выражения с использованием точечного синтаксиса, я ожидаю, что они будут простой привязкой к ivar. Это не всегда так. Рассмотрим объект контроллера, который опосредует массив и табличное представление. Если я вызову myController.contentArray = newArray;, я ожидаю, что он заменит старый массив новым массивом. Однако исходный программист мог бы переопределить setContentArray:, чтобы не только установить массив, но и перезагрузить tableview. С линии нет никаких указаний на это поведение. Если бы я увидел [myController setContentArray:newArray];, я бы подумал: "Ага, метод. Мне нужно взглянуть на определение этого метода, чтобы убедиться, что я знаю, что он делает".

Итак, я думаю, что мое резюме Beef # 2 состоит в том, что вы можете переопределить значение синтаксиса точки с помощью специального кода.

Говядина # 3: Я думаю, что это выглядит плохо. Как программист Objective-C, я полностью использую синтаксис, чтобы читать и видеть строки и строки красивых скобок, а затем внезапно разбиваться на foo.name = newName; foo.size = newSize; и т.д. Немного отвлекает меня. Я понимаю, что некоторые вещи требуют точечного синтаксиса (C structs), но это единственный раз, когда я их использую.

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

Недавнее сообщение в блоге против синтаксиса точки: http://weblog.bignerdranch.com/?p=83

Возврат к следующему сообщению: http://eschatologist.net/blog/?p=226 (с оригинальной статьей в пользу синтаксиса точки: <а2 > )

Ответ 3

Я новый разработчик Cocoa/Objective-C, и я беру его на себя:

Я придерживаюсь нотации обмена сообщениями, хотя я начал с Obj-C 2.0, и хотя точечное обозначение более знакомо (Java - это мой первый язык). Моя причина для этого довольно проста: я до сих пор не знаю, точно понять, почему они добавили точечную нотацию в язык. Для меня это кажется ненужным, "нечистым" дополнением. Хотя, если кто-то может объяснить, как это приносит пользу языку, я был бы рад услышать его.

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

Ответ 4

Objective-C dot notation - это синтаксический сахар, который переводится в обычное сообщение, поэтому под капотом ничего не меняется и не имеет никакого значения во время выполнения. Точечная нотация - это не быстрее, чем передача сообщений.

После этого понадобилась небольшая преамбула, которую здесь видели и плюсы и минусы:

Дословные обозначения за и против

  • <сильные > плюсы

    • читаемость: точечное обозначение легче читать, чем перенос вложенных скобок.
    • Это упрощает взаимодействие с атрибутами и свойствами: с использованием точечной нотации для свойств и нотации сообщений для методов, которые вы можете добиться разделения состояния и поведения на уровне синтаксиса.
    • Можно использовать оператор составного присваивания (1).
    • с использованием @property и точечной нотации, которую компилятор выполняет для вас много, он может генерировать код для хорошего управления памятью при получении и настройке свойства; вот почему точечные обозначения предлагаются самими официальными руководствами Apple.
  • <сильные > минусы

    • Точечная запись разрешена только для доступа к объявленному @property
    • Так как Objective-C является слоем выше стандартного C (расширение языка), точечное обозначение действительно не делает ясным, если доступный объект является объектом или структурой. Часто, похоже, вы обращаетесь к свойствам структуры.
    • вызов метода с точечной нотации вы теряете названные параметры преимущества чтения
    • когда смешанная нотация сообщений и точечное обозначение кажутся такими, что вы кодируете на двух разных языках.

Примеры кода:

(1) Пример кода для примера использования сложного оператора:

//Use of compound operator on a property of an object
anObject.var += 1;
//This is not possible with standard message notation
[anObject setVar:[anObject var] + 1];

Ответ 5

Использование стиля языка, соответствующего самому языку, является лучшим советом здесь. Однако это не относится к написанию функционального кода в OO-системе (или наоборот), а точечное обозначение является частью синтаксиса в Objective-C 2.0.

Любая система может быть использована неправильно. Существование препроцессора на всех языках, основанных на C, достаточно, чтобы сделать действительно довольно странные вещи; просто посмотрите на Obfuscated C Contest, если вам нужно посмотреть, как это странно. Означает ли это, что препроцессор автоматически плох и что вы никогда не должны его использовать?

Использование точечного синтаксиса для доступа к свойствам, которые были определены как таковые в интерфейсе, открыто для злоупотреблений. Существование злоупотреблений в потенции не обязательно должно быть аргументом против него.

Доступ к свойствам может иметь побочные эффекты. Это ортогонально синтаксису, используемому для получения этого свойства. CoreData, делегирование, динамические свойства (first + last = full) будут обязательно выполнять некоторую работу под обложками. Но это будет путать "переменные экземпляра" с "свойствами" объекта. Нет причин, по которым свойства должны обязательно храниться как есть, особенно если они могут быть вычислены (например, длина строки). Поэтому, если вы используете foo.fullName или [foo fullName], все равно будет динамическая оценка.

Наконец, поведение свойства (при использовании как lvalue) определяется самим объектом, например, выполняется ли копия или сохраняется ли она. Это облегчает изменение поведения позже - в самом определении свойства - вместо необходимости повторного внедрения методов. Это добавляет гибкости подхода, в результате чего возникает вероятность возникновения ошибок (реализации). По-прежнему существует возможность выбора неправильного метода (т.е. Копирования вместо сохранения), но это проблема архитектуры, а не проблема реализации.

В конечном счете, это сводится к тому, что "это похоже на вопрос структуры". На данный момент это, пожалуй, главный отличительный признак дебатов; если у вас есть структура, она работает иначе, чем если у вас есть объект. Но это всегда было правдой; вы не можете отправить сообщение struct, и вам нужно знать, основана ли она на основе стека или reference/malloc. Существуют уже ментальные модели, которые отличаются в терминах использования ([[CGRect alloc] init] или struct CGRect?). Они никогда не были унифицированы с точки зрения поведения; вам нужно знать, с чем вы имеете дело в каждом случае. Добавление обозначения объектов для объектов очень маловероятно, чтобы запутать любого программиста, который знает, каковы их типы данных; и если они этого не делают, у них большие проблемы.

Что касается согласованности; (Objective-) C несовместим внутри себя. = используется как для назначения, так и для равенства, на основе лексической позиции в исходном коде. * используется для указателей и умножения. BOOL - это символы, а не байты (или другое целочисленное значение), несмотря на то, что YES и NO равны 1 и 0 соответственно. Согласованность или чистота - это не то, для чего был разработан язык; речь шла о том, чтобы все было сделано.

Итак, если вы не хотите его использовать, не используйте его. Сделайте это по-другому. Если вы хотите использовать его, и вы это понимаете, это хорошо, если вы его используете. Другие языки имеют дело с концепциями общих структур данных (maps/structs) и типов объектов (со свойствами), часто использующими один и тот же синтаксис для обоих, несмотря на то, что один является просто структурой данных, а другой - богатым объектом. Программисты в Objective-C должны иметь эквивалентную способность иметь возможность работать со всеми стилями программирования, даже если это не ваш предпочтительный.

Ответ 6

Я использую его для свойств, потому что

for ( Person *person in group.people){ ... }

немного легче читать, чем

for ( Person *person in [group  people]){ ... }

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

Я также буду использовать его при изменении коллекции, например:

[group.people addObject:another_person];

является более читаемым, чем

[[group people] addObject:another_person];

Акцент в этом случае должен заключаться в действии добавления объекта в массив вместо цепочки двух сообщений.

Ответ 7

В основном я вырос в возрасте Objective-C 2.0, и я предпочитаю точечную нотацию. Для меня это позволяет упростить код, вместо дополнительных скобок, я могу просто использовать точку.

Мне также нравится синтаксис точки, потому что он действительно чувствует, что я обращаюсь к свойству объекта, вместо того, чтобы просто отправлять ему сообщение (конечно, точечный синтаксис действительно переводит на отправку сообщений, но для ради видимости, точка чувствует себя по-другому). Вместо того, чтобы "вызвать геттер" с помощью старого синтаксиса, мне действительно кажется, что я получаю что-то полезное от объекта.

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

**** Редактирование: как указано в bbum, вы также можете использовать dot-синтаксис для вызова любого метода на объекте (я не знал об этом). Поэтому я скажу, что мое мнение о точечном синтаксисе касается только свойств объекта, а не ежедневной отправки сообщений **

Ответ 8

Я предпочитаю синтаксис сообщений... но только потому, что это то, чему я научился. Учитывая множество моих классов и то, что не в стиле Objective-C 1.0, я бы не хотел их смешивать. У меня нет реальной причины, кроме "того, к чему я привык", чтобы не использовать синтаксис точки... ЗА ИСКЛЮЧЕНИЕМ этого, это заставляет меня INSANE

[myInstance.methodThatReturnsAnObject sendAMessageToIt]

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

[[myInstance methodThatReturnsAnObject] sendAMessageToIt]

более читабельна. Но каждому свое!

Ответ 9

Честно говоря, я думаю, что это сводится к вопросу о стиле. Я лично против синтаксиса точки (особенно после того, как выяснилось, что вы можете использовать его для вызовов методов, а не только для чтения/записи переменных). Однако, если вы собираетесь использовать его, я бы настоятельно рекомендовал не использовать его для чего-либо, кроме доступа и изменения переменных.

Ответ 10

Одним из основных преимуществ объектно-ориентированного программирования является отсутствие прямого доступа к внутреннему состоянию объектов.

Синтаксис Dot кажется мне попыткой заставить его выглядеть и чувствовать, как будто доступ к состоянию напрямую. Но на самом деле это просто синтаксический сахар над поведением -foo и -setFoo:. Сам я предпочитаю называть лопату лопатой. Точечный синтаксис помогает читабельности в той мере, в которой код более краток, но это не помогает понять, потому что не следует помнить, что вы действительно вызываете -foo и -setFoo: может вызвать проблемы.

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

В целом, я бы предпочел синтаксис точек, и свойства никогда не были введены. Раньше я мог сказать людям, что ObjC - это несколько чистых расширений на C, чтобы сделать его более похожим на Smalltalk, и я больше не думаю, что это правда.

Ответ 11

По-моему, синтаксис точки делает Objective-C меньше Smalltalk-esque. Это может сделать код более простым, но добавляет неоднозначность. Это struct, union или объект?

Ответ 12

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

Вот почему я верю в мысль о том, что "синтаксис" точка-точка ", в котором вы думаете, что вы обращаетесь к переменной, так что это запутывает", неверно. Точка или скобка, вы не должны делать предположений о внутренних элементах: это свойство, а не ivar.

Ответ 13

Я думаю, что я могу переключиться на обмен сообщениями вместо точечной нотации, потому что в моей голове object.instanceVar - это только instanceVar, который принадлежит объекту, для меня он вообще не выглядит как вызов метода что это так, поэтому в вашем аксессуре могут быть вещи, и вы используете instanceVar или self.instanceVar, может иметь гораздо большую разницу, чем просто неявное или явное. Просто мои 2 ¢.

Ответ 14

Точечная нотация пытается сделать сообщения похожими на обращения к члену структуры, а это не так. В некоторых случаях может работать нормально. Но скоро кто-то придумает что-то вроде этого:

NSView *myView = ...;
myView.frame.size.width = newWidth;

Выглядит хорошо. Но нет. Это то же самое, что

[myView frame].size.width = newWidth;

который не работает. Компилятор принимает первый, но по праву не второй. И даже если он выпустил ошибку или предупреждение для первого, это просто запутывает.

Ответ 15

Назовите меня ленивым, но если мне пришлось набирать сингл '.' против двух [] каждый раз, чтобы получить те же результаты, я бы предпочел сингл. Я ненавижу многословные языки.() В lisp загнал меня в орехи. Элегантный язык, такой как математика, является кратким и эффективным, а все остальные - короткими.

Ответ 16

Использовать точечную нотацию (всякий раз, когда вы можете)

В случае методов, возвращающих некоторое значение

Не использовать точечную нотацию

В том случае, когда методы возвращают void, методы init или метод класса.

И мое личное любимое исключение

NSMutableArray * array = @[].mutableCopy;

Ответ 17

Я лично не использую точечные обозначения в коде. Я использую его только в выражении привязки CoreData KVC, когда это требуется.

Причиной не использовать их в коде для меня является то, что точка-нотация скрывает семантику сеттера. Установка свойства в точечной нотации всегда выглядит как присваивание, независимо от семантики сеттера (присваивание/сохранение/копирование). Использование сообщения-уведомления делает видимым, что принимающий объект имеет контроль над тем, что происходит в сеттер, и подчеркивает тот факт, что эти эффекты необходимо учитывать.

Я все еще думаю, могу ли я использовать dot-notation при получении значения совместимого или объявленного свойства KVC, потому что он, по общему признанию, немного компактнее и читабельнее, и нет скрытой семантики. Прямо сейчас я придерживаюсь сообщения-уведомления ради последовательности.

Ответ 18

ОК, точечная нотация в Objective-C выглядит странно. Но я все равно не могу без этого сделать следующее:

int width = self.frame.size.width;

Работает нормально, но:

int height = [[[self frame] size] height];

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

Ответ 19

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

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