Что предпочтительнее в target-c: id или явном типе? - PullRequest
2 голосов
/ 16 января 2011

Что лучше и почему?

Что лучше в таких ситуациях, как метод init класса и обычные переменные в коде?

Ответы [ 5 ]

11 голосов
/ 16 января 2011

Что лучше и почему?

Явная информация о наборе всегда лучше, если вы просто не можете ее использовать по какой-либо причине (см. Ниже).

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

Давным-давно, все в используемых API-интерфейсах id.Это оказалось полной болью в заднице;хрупкий и привел ко многим сбоям, которые могли быть обнаружены с определенными типами.

Итак, это было изменено.(Это было ~ 1994).

Что лучше в таких ситуациях, как метод инициализации класса и обычные переменные в коде?

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

То же самое относится к retain, objectAtIndex:, addObject: и многие другие методы, которые принимают или возвращают один из множества видов объектов (или принимают их в качестве аргументов).

И, нет, абсолютно никакой разницы в производительности между id и, скажем, NSView*.

Не могли бы вы привести пример, когда явная типизация вызовет проблему, пожалуйста?

Если вы написали:

- (MyClass *) init;

И в подклассе:

- (MySubclass *) init;

Скорее всего, вы получите предупреждения компилятора о wazoo, или вам придется типизировать wazoo.

5 голосов
/ 30 марта 2012

На последних версиях clang (в Lion) вы не должны возвращать id, а вместо этого возвращать instancetype.Это ключевое слово, которое используется в возвращаемых типах, чтобы указать, что возвращаемый тип является экземпляром класса, получающего сообщение.Теперь это предпочтительный тип возврата для методов инициализации в OS X Lion.

4 голосов
/ 16 января 2011

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

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

Это также полезно для будущих программистов (включая вашу будущую личность), пытающихся работать с вашим кодом, что повышает вероятность того, что они смогут сразу определить, каким должен быть объект. В результате код становится более «самодокументированным».

Некоторые вещи не могут иметь осмысленного типа, потому что на самом деле тип не применяется. В других случаях вам нужно использовать id, потому что вы должны быть в состоянии принять любой тип объекта. Cocoa Touch использует его, например, при обращении к sender сообщения, поскольку его могло отправить что угодно; указание явного типа просто не сработает.

Тем не менее, подавляющее большинство времени в ваших интересах явный тип.

2 голосов
/ 16 января 2011

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

Например, свойство dataSource UITableView объявлено как id<UITableViewDataSource>, поскольку табличное представление заботится только о том, что его источник данныхэто некоторый объект, который соответствует протоколу UITableViewDataSource.Это позволяет источнику данных быть достаточно гибким для использования с любым конкретным классом, который реализует протокол, но все же позволяет компилятору предупреждать вас, если вы пытаетесь назначить объект, который не реализует этот протокол, в качестве источника данных.

Если вы слишком конкретны, тогда ваш код становится негибким, принимая только конкретные реализации, которые не являются строго необходимыми (например, требуют NSMutableString, когда вы действительно могли бы работать с любой строкой NSString).

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

Для init методы следуют советам в Язык программирования Objective-C

Возвращаемый тип метода инициализатора должен быть id.

Причина в том, что id дает указание на то, чтокласс целенаправленно не учитываетсякрасный - класс не указан и может быть изменен в зависимости от контекста вызова.Например, NSString предоставляет метод initWithFormat :.Однако при отправке экземпляру NSMutableString (подкласс NSString) сообщение возвращает экземпляр NSMutableString, а не NSString.(См. Также пример синглтона, приведенный в «Объединении распределения и инициализации».)

0 голосов
/ 16 января 2011

Я не думаю, что есть разница в производительности между ними. Вы можете позволить идентификатору возвращать тип для init, потому что вы можете привести результат вашего init.

Например:

Toto *foo = [[Toto alloc] init];
id foo2 = [[Toto alloc] init]; 

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

Я думаю, что некоторые разработчики позволяют id, потому что они просто передают туда переменную через экземпляр и не используют его. Такого рода использование позволяет не импортировать .h

С уважением,
KL94

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