Теперь у нас есть "точечная" запись свойств. Я видел различные спины и Фортов о достоинствах точечной нотации против сообщения нотации. Чтобы не запятнать ответы, я не собираюсь отвечать в этом вопросе.
Что вы думаете о точечной нотации и нотации сообщений для доступа к свойствам?
Пожалуйста, постарайтесь сосредоточить внимание на Objective-C - мое единственное предубеждение, которое я изложу, заключается в том, что Objective-C - это Objective-C, поэтому ваше предпочтение, чтобы оно было похоже на Java или JavaScript, недопустимо.
Допустимые комментарии касаются технических вопросов (порядок операций, приоритет приведения, производительность и т. Д.), Ясности (структура против характера объекта, как за, так и против!), Краткости и т. Д.
Обратите внимание: я принадлежу к школе строгого качества и удобочитаемости кода, так как работал над огромными проектами, где соглашение и качество кода имеют первостепенное значение (парадигма «запись один раз прочитала тысячу раз»).
Ответы:
Не используйте точку для обозначения поведения. Используйте точку для доступа или установки атрибута, такого как материал, обычно атрибутов, объявленных как свойства.
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 расширит возможности, позволяя вам проверять, используется ли точка только для определенных шаблонов или нет для некоторых других шаблонов.
источник
.uppercaseString
если бы классу было разрешено выражать свое намерение и иметь его обеспечивается компилятором. Возможно, мне не хватает чего-то, что требует текущей реализации точечной записи.@property
только, но это потребовало бы от потребителя API изучения другого логического измерения информации и от разработчиков API, которые, скорее всего, утонули в спорах о том, что должно и не должно быть@property
. Обратите внимание, что Xcode предпочитает - более серьезно -@property
подразумеваемые методы при завершении кода ... Это приветствуется, но не применяется.@property
объявленными средствами доступа только тогда, когда вы новичок в языке. По мере того, как человек приобретает уверенность в программировании на Objective-C, делайте то, что считаете правильным. Интересно; многие из нас вернулись к очень ограниченному использованию точки.Позвольте мне начать с того, что я начал программировать на Visual / Real Basic, а затем перешел на Java, поэтому я довольно привык к синтаксису точек. Однако когда я наконец перешел на Objective-C и привык к скобкам, а затем увидел введение Objective-C 2.0 и его точечный синтаксис, я понял, что мне это действительно не нравится. (для других языков нормально, потому что так катят).
У меня есть три основных недостатка с точечным синтаксисом в Objective-C:
Говядина №1: из-за этого неясно, почему вы можете получать ошибки. Например, если у меня есть строка:
something.frame.origin.x = 42;
Тогда я получу ошибку компилятора, потому что
something
это объект, и вы не можете использовать структуры объекта в качестве 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:
не только установить массив, но и перезагрузить табличное представление. Судя по строке, нет никаких указаний на такое поведение. Если бы я увидел[myController setContentArray:newArray];
Итак, я думаю, что мое резюме Beef # 2 состоит в том, что вы можете переопределить значение синтаксиса точки с помощью специального кода.
Говядина №3: Я думаю, это плохо выглядит. Как программист Objective-C, я полностью привык к синтаксису в скобках, так что читать и видеть строки и строки красивых скобок, а затем внезапно ломаться с и
foo.name = newName; foo.size = newSize;
т.д. меня немного отвлекает. Я понимаю, что для некоторых вещей требуется точечный синтаксис (структуры C), но это единственный раз, когда я их использую.Конечно, если вы пишете код для себя, используйте то, что вам удобно. Но если вы пишете код, который планируете использовать с открытым исходным кодом, или пишете что-то, что не ожидаете поддерживать вечно, я настоятельно рекомендую использовать синтаксис скобок. Это, конечно, только мое мнение.
Недавнее сообщение в блоге против синтаксиса точки: http://weblog.bignerdranch.com/?p=83
Опровержение вышеуказанного сообщения: http://eschatologist.net/blog/?p=226 (с оригинальной статьей в пользу синтаксиса с точкой: http://eschatologist.net/blog/?p=160 )
источник
something
это объект, но я встречал пару мест, где оригинальные авторы создавали структуры (для скорости, меньшего использования памяти и т. Д.), И мне нужно потратить пару минут, пытаясь понять, почему код не работает. t компилировать.Я новый разработчик Cocoa / Objective-C, и мое мнение таково:
Я придерживаюсь нотации сообщений, хотя я начал с Obj-C 2.0, и хотя точечная нотация кажется мне более знакомой (Java - мой первый язык). Причина этого довольно проста: я до сих пор не совсем понимаю почему они добавили в язык точечную нотацию. Мне это кажется ненужным, «нечистым» дополнением. Хотя, если бы кто-нибудь мог объяснить, какую пользу это приносит языку, я был бы рад это услышать.
Однако я считаю это стилистическим выбором и не думаю, что существует правильный или неправильный способ, если он согласован и читабелен , как и любой другой стилистический выбор (например, поставить открывающую фигурную скобку на той же строке, что и заголовок метода или следующую строку).
источник
Точечная нотация Objective-C - это синтаксический сахар, который переводится в нормальную передачу сообщений, поэтому внутренне ничего не меняет и не имеет значения во время выполнения. Точечная запись абсолютно не быстрее передачи сообщений.
После этого нужна небольшая преамбула, вот плюсы и минусы, которые я видел:
Плюсы и минусы точечной записи
профи
@property
нотацию и точечную нотацию, компилятор сделает за вас много работы, он может сгенерировать код для хорошего управления памятью при получении и установке свойства; Вот почему точечная нотация предлагается в официальных руководствах самой Apple.минусы
@property
Примеры кода:
(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];
источник
Лучшим советом здесь является использование стиля языка, соответствующего самому языку. Однако это не относится к написанию функционального кода в объектно-ориентированной системе (или наоборот), и точечная нотация является частью синтаксиса в Objective-C 2.0.
Любая система может быть использована неправильно. Существования препроцессора во всех языках, основанных на C, достаточно, чтобы делать действительно довольно странные вещи; просто посмотрите на Contest Obfuscated C если вам нужно точно понять, насколько странным он может быть. Означает ли это, что препроцессор автоматически становится плохим и вам никогда не следует его использовать?
Использование точечного синтаксиса для доступа к свойствам, которые были определены как таковые в интерфейсе, открыто для злоупотреблений. Существование потенциального злоупотребления не обязательно должно быть аргументом против него.
Доступ к собственности может иметь побочные эффекты. Это ортогонально синтаксису, используемому для получения этого свойства. CoreData, делегирование, динамические свойства (first + last = full) - все это обязательно выполняет некоторую скрытую работу. Но это привело бы к путанице «переменные экземпляра» со «свойствами» объекта. Нет причин, по которым свойства должны обязательно храниться как есть, особенно если они могут быть вычислены (например, длина строки). Так что независимо от того, используете ли вы foo.fullName или [foo fullName], все равно будет динамическая оценка.
Наконец, поведение свойства (при использовании в качестве lvalue ) определяется самим объектом, например, будет ли сделана копия или сохранена. Это упрощает изменение поведения позже - в самом определении свойства - вместо повторной реализации методов. Это увеличивает гибкость подхода, в результате чего вероятность возникновения меньшего количества ошибок (реализации). По-прежнему существует возможность выбрать неправильный метод (т.е. скопировать вместо сохранения), но это проблема архитектуры, а не реализации.
В конечном итоге, все сводится к вопросу «похоже ли это на структуру». Это, вероятно, основная разница в дебатах до сих пор; если у вас есть структура, она работает иначе, чем если бы у вас есть объект. Но это всегда было правдой; вы не можете отправить структуру сообщения, и вам нужно знать, на основе стека или ссылки / malloc. Уже существуют ментальные модели, которые различаются по использованию ([[CGRect alloc] init] или struct CGRect?). Они никогда не были едины в поведении; вам нужно знать, с чем вы имеете дело в каждом конкретном случае. Добавление обозначения свойств для объектов вряд ли запутает любого программиста, который знает, каковы их типы данных; а если нет, то у них проблемы посерьезнее.
Что касается последовательности; (Цель-) C противоречиво внутри себя. = используется как для присваивания, так и для равенства в зависимости от лексической позиции в исходном коде. * используется для указателей и умножения. BOOL - это символы, а не байты (или другое целочисленное значение), несмотря на то, что YES и NO равны 1 и 0 соответственно. Последовательность или чистота - это не то, для чего был разработан язык; это было о том, чтобы добиться цели.
Так что, если вы не хотите его использовать, не используйте его. Сделайте это по-другому. Если вы хотите его использовать и понимаете, это нормально, если вы им воспользуетесь. Другие языки имеют дело с концепциями общих структур данных (карты / структуры) и типов объектов (со свойствами), часто используя один и тот же синтаксис для обоих, несмотря на то, что один является просто структурой данных, а другой - многофункциональным объектом. Программисты на Objective-C должны иметь эквивалентные способности, чтобы иметь дело со всеми стилями программирования, даже если они вам не нравятся.
источник
Я использую его для свойств, потому что
for ( Person *person in group.people){ ... }
читать немного легче, чем
for ( Person *person in [group people]){ ... }
во втором случае читаемость прерывается, когда ваш мозг переводится в режим отправки сообщений, тогда как в первом случае ясно, что вы получаете доступ к свойству people объекта группы.
Я также буду использовать его при изменении коллекции, например:
немного читабельнее, чем
Акцент в этом случае должен быть сделан на добавлении объекта в массив вместо объединения двух сообщений.
источник
В основном я вырос в эпоху Objective-C 2.0 и предпочитаю точечную нотацию. Для меня это позволяет упростить код, вместо дополнительных скобок я могу просто использовать точку.
Мне также нравится точечный синтаксис, потому что он заставляет меня чувствовать, что я обращаюсь к свойству объекта, а не просто отправляю ему сообщение (конечно, точечный синтаксис действительно переводится в отправку сообщения, но для внешнего вида , точка ощущается иначе). Вместо того, чтобы «вызывать геттер» по старому синтаксису, мне кажется, что я напрямую получаю что-то полезное от объекта.
Некоторые дискуссии по этому поводу связаны с тем, что «Но у нас уже есть точечный синтаксис, и он для
structs
!». И это правда. Но (и опять же, это чисто психологически) я чувствую то же самое. Доступ к свойству объекта с использованием точечного синтаксиса ощущается так же, как доступ к члену структуры, что более или менее является предполагаемым эффектом (на мой взгляд).**** Изменить: как указал bbum, вы также можете использовать точечный синтаксис для вызова любого метода объекта (я не знал об этом). Поэтому я скажу, что мое мнение о синтаксисе точек предназначено только для работы со свойствами объекта, а не для повседневной отправки сообщений **
источник
Я предпочитаю синтаксис обмена сообщениями ... но только потому, что я этому научился. Учитывая, что многие из моих классов и те, что не относятся к стилю Objective-C 1.0, я бы не хотел смешивать их. У меня нет реальной причины, кроме «того, к чему я привык», чтобы не использовать точечный синтаксис ... КРОМЕ этого, это сводит меня с ума
Не знаю почему, но меня это действительно бесит, без уважительной причины. Я просто думаю, что делаю
читабельнее. Но каждому свое!
источник
[self.title lowercaseString]
что ли. Но стилистически я вижу, почему смешивать и согласовывать синтаксис утомительно. Единственная причина, по которой я это делаю, - это четко понимать, что такое свойство, а что метод, возвращающий объект (я знаю, что свойства - это всего лишь свойства, но, надеюсь, вы понимаете, о чем я).Честно говоря, я думаю, дело в стиле. Я лично против точечного синтаксиса (особенно после того, как только узнал, что вы можете использовать его для вызовов методов, а не только для чтения / записи переменных). Однако, если вы собираетесь его использовать, я настоятельно рекомендую не использовать его для чего-либо, кроме доступа к переменным и их изменения.
источник
Одним из основных преимуществ объектно-ориентированного программирования является отсутствие прямого доступа к внутреннему состоянию объектов.
Мне кажется, что точечный синтаксис - это попытка создать впечатление, будто к состоянию осуществляется прямой доступ. Но на самом деле это просто синтаксический сахар над поведением -foo и -setFoo :. Лично я предпочитаю называть вещи своими именами. Точечный синтаксис способствует удобочитаемости в той степени, в которой код более лаконичен, но он не помогает пониманию, потому что игнорирование того, что вы действительно вызываете -foo и -setFoo:, может означать проблемы.
Мне кажется, что синтезированные аксессоры - это попытка упростить запись объектов, к состоянию которых осуществляется прямой доступ. Я считаю, что это способствует созданию именно такого типа программ, для предотвращения которого создавалось объектно-ориентированное программирование.
В целом, я бы предпочел точечный синтаксис и свойства, которые никогда не вводились. Раньше я мог говорить людям, что ObjC - это несколько чистых расширений для C, чтобы сделать его более похожим на Smalltalk, и я больше не думаю, что это правда.
источник
На мой взгляд, точечный синтаксис делает Objective-C менее похожим на Smalltalk. Код может выглядеть проще, но добавляет двусмысленности. Это
struct
,union
или объект?источник
Многие люди, кажется, путают «свойства» с «переменными экземпляра». Я думаю, что смысл свойств состоит в том, чтобы сделать возможным изменение объекта без необходимости знать его внутреннее устройство. Переменная экземпляра в большинстве случаев является «реализацией» свойства (которое, в свою очередь, является «интерфейсом»), но не всегда: иногда свойство не соответствует ivar, а вместо этого вычисляет возвращаемое значение. на лету'.
Вот почему я считаю, что идея о том, что «точечный синтаксис обманывает вас, заставляя думать, что вы обращаетесь к переменной, так что это сбивает с толку», неверна. Точка или скобка, вы не должны делать предположений о внутреннем устройстве: это свойство, а не ivar.
источник
->
который выполняет эту роль (конечно, если доступ к указанным ivars не ограничен).Я думаю, что мог бы переключиться на обмен сообщениями вместо точечной нотации, потому что в моей голове object.instanceVar - это просто instanceVar , принадлежащий объекту , для меня это совсем не похоже на вызов метода , что есть, поэтому может быть что-то on в вашем методе доступа и от того, используете ли вы instanceVar или self.instanceVar, может быть гораздо больше различий, чем просто неявное или явное. Просто мои 2 цента.
источник
Точечная нотация пытается сделать сообщения похожими на доступ к члену структуры, а это не так. В некоторых случаях может работать нормально. Но скоро кто-то придумает что-то вроде этого:
NSView *myView = ...; myView.frame.size.width = newWidth;
Выглядит хорошо. Но нет. Это то же самое, что и
что не работает. Компилятор принимает первое, но по праву не принимает второе. И даже если он сначала выдал ошибку или предупреждение, это просто сбивает с толку.
источник
Назовите меня ленивым, но если бы мне пришлось напечатать сингл '.' по сравнению с двумя [] каждый раз, чтобы получить те же результаты, я бы предпочел сингл. Я ненавижу многословные языки. () В lisp сводил меня с ума. Элегантный язык, такой как математика, краток и эффективен, все остальные не оправдывают ожиданий.
источник
Используйте точечную нотацию (когда можете)
В методах экземпляра, возвращающих некоторое значение
Не используйте точечную нотацию
В методах экземпляра, возвращающих void, в методах инициализации или в методе класса.
И мое личное любимое исключение
NSMutableArray * array = @[].mutableCopy;
источник
Лично я вообще не использую точечную нотацию в коде. Я использую его только в выражении привязки CoreData KVC, когда это необходимо.
Причина, по которой я не использую их в коде, заключается в том, что точечная нотация скрывает семантику установщика. Установка свойства в точечной нотации всегда выглядит как присваивание независимо от семантики установщика (присваивать / сохранять / копировать). Использование нотации сообщения делает видимым, что принимающий объект имеет контроль над тем, что происходит в установщике, и подчеркивает тот факт, что эти эффекты необходимо учитывать.
Я все еще обдумываю, могу ли я использовать точечную нотацию при извлечении значения KVC-совместимого или объявленного свойства, потому что оно, по общему признанию, немного более компактно и читабельно и не имеет скрытой семантики. Сейчас я придерживаюсь обозначения сообщений для единообразия.
источник
Хорошо, точечная запись в Objective-C действительно выглядит странно. Но без него я до сих пор не могу:
int width = self.frame.size.width;
Работает нормально, но:
int height = [[[self frame] size] height];
Выдает мне «Невозможно преобразовать в тип указателя». Однако мне бы очень хотелось, чтобы мой код выглядел согласованным с нотацией сообщений.
источник
Это отличный вопрос, и я вижу много разных ответов на него. Хотя многие затронули эти темы, я постараюсь ответить на это под другим углом (некоторые могли сделать это неявно):
Если мы используем нотацию «точка», разрешение цели для метода выполняется во время компиляции. Если мы используем передачу сообщений, разрешение цели откладывается до выполнения во время выполнения. Если цели решаются во время компиляции, выполнение происходит быстрее, так как разрешение целей во время выполнения включает несколько накладных расходов. (Не то чтобы разница во времени будет иметь большое значение). Поскольку мы уже определили свойство в интерфейсе объекта, нет смысла отличать разрешение цели для свойства от времени выполнения, и, следовательно, точечная нотация - это обозначение, которое мы должны использовать для доступа к свойству.
источник