В чем разница между #import и @class, и когда я должен использовать один поверх другого? - PullRequest
30 голосов
/ 31 октября 2008

Я учил себя Objective-C в течение последнего месяца или около того (я являюсь руководителем Java), и теперь мой мозг обволакивает большую часть этого. Одна вещь, которая меня сейчас смущает: какая разница между импортом класса через @class и выполнением #import?

Является ли один лучше другого, или мне нужно использовать одно вместо другого в некоторых случаях? До сих пор я использовал только #import.

Ответы [ 3 ]

66 голосов
/ 31 октября 2008

#import переносит весь рассматриваемый файл заголовка в текущий файл; любые файлы, которые этот файл #import s также включены. @class, с другой стороны (когда он используется в строке с некоторыми именами классов), просто говорит компилятору: «Эй, скоро вы увидите новый токен; это класс, так что относитесь к нему таким образом).

Это очень полезно, когда у вас есть потенциал для «круговых включений»; т.е. Object1.h ссылается на Object2, а Object2.h ссылается на Object1. Если вы поместите #import оба файла в другой, компилятор может запутаться, когда попытается #import Object1.h, заглянет в него и увидит Object2.h; он пытается #import Object2.h и видит Object1.h и т. д.

Если, с другой стороны, каждый из этих файлов имеет @class Object1; или @class Object2;, то круговая ссылка отсутствует. Просто убедитесь, что на самом деле #import необходимые заголовки в файлах вашей реализации (.m).

27 голосов
/ 31 октября 2008

@class называется предварительным объявлением . Вы в основном говорите компилятору о том, что класс существует, но не о классе. Таким образом, он не знает таких вещей, как суперкласс и какие методы он объявляет.

Как правило, используйте @class в .h и #import в .m, если это вообще возможно. Как сказал Луи, это поможет ускорить компиляцию. Однако бывает, что вам нужно #import класс в заголовке. Я могу подумать о следующих случаях:

  • Вы создаете подкласс другого класса
  • Вы реализуете протокол

В этих случаях вы должны #import файл заголовка, в котором объявлен класс или протокол, поскольку компилятору необходимо знать полную иерархию классов своих родительских классов и реализующие протоколы.

FWIW, вы также можете пересылать объявления протоколов, если вы их не реализуете:

@protocol SomeProtocol;

@interface ...

- (id<SomeProtocol>)someMethod;

@end
5 голосов
/ 31 октября 2008

Еще одна вещь, которую вы должны иметь в виду, это то, что #imports замедляет время компиляции, поскольку это означает, что компилятор должен извлекать и работать с гораздо большим количеством заголовочных файлов. Это в основном маскируется использованием предварительно скомпилированных заголовков, но мне иногда передавали проекты, в которых corss импортировал каждый заголовок вместо использования @class там, где это необходимо, и исправление их может улучшить время компиляции. Это тонкий способ, которым система укрепляет тот факт, что если вы используете только то, что вам действительно нужно, дела идут быстрее.

Как правило, я всегда использую объявления @class в своих заголовочных файлах и только #import суперкласса. Это согласуется с предложениями Бена, но я подумал, что стоит отметить, что, даже если вы не беспокоитесь о циклических ссылках, неплохо ограничить #imports в заголовочных файлах, если вы можете.

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