Какая разница между #import и @class, и когда я должен использовать один над другим?
Я учил себя Objective-C за последний месяц или около того (я - глава Java), и теперь у меня есть мозг вокруг большей части его. Одна вещь, которая меня путала в данный момент: Какая разница между импортом класса через @class и выполнением #import?
Это лучше, чем другой, или мне нужно использовать один вместо другого в определенных случаях? До сих пор я использовал только #import.
Ответы
Ответ 1
#import
выводит весь заголовочный файл в текущий файл; все файлы, в которые включен файл #import
. @class, с другой стороны (при использовании в отдельной строке с некоторыми именами классов), просто сообщает компилятору "Эй, скоро вы увидите новый токен, это класс, так что относитесь к нему так).
Это очень полезно, когда у вас есть потенциал для "круговых включений"; т.е. Object1.h ссылается на Object2, а Object2.h ссылается на Object1. Если вы #import
оба файла в другом, компилятор может запутаться, когда он пытается #import
Object1.h, смотрит в него и видит Object2.h; он пытается #import
Object2.h и видит Object1.h и т.д.
Если, с другой стороны, каждый из этих файлов имеет @class Object1;
или @class Object2;
, тогда нет круговой ссылки. Просто убедитесь, что на самом деле #import
требуемые заголовки в ваших файлах реализации (.m).
Ответ 2
@class
называется форвардным объявлением. Вы в основном говорите компилятору, что класс существует, но не что-то вроде класса. Таким образом, он не знает таких вещей, как его суперкласс и какие методы он декларирует.
Как правило, используйте @class
в .h и #import
в .m, если это вообще возможно. Как сказал Луис, это поможет ускорить время компиляции. Однако есть моменты, когда вам нужно #import
класс в заголовке. Случаи, о которых я сейчас думаю, следующие:
- Вы подклассифицируете другой класс
- Вы реализуете протокол
В этих случаях вы должны #import
заголовочный файл, где объявлен класс или протокол, потому что компилятор должен знать полную иерархию классов своих родительских классов и протоколы реализации.
FWIW, вы также можете перенаправлять протоколы объявлений, пока вы их не выполняете:
@protocol SomeProtocol;
@interface ...
- (id<SomeProtocol>)someMethod;
@end
Ответ 3
Другая вещь, которую вы хотите иметь в виду, - это то, что #imports замедляет время компиляции, поскольку это означает, что компилятору нужно тянуть и работать с гораздо большим количеством файлов заголовков. Это в основном маскируется использованием предварительно скомпилированных заголовков, но мне иногда дают проекты, которые корс импортировал каждый заголовок, а не при необходимости, используя @class, и исправление их может улучшить время компиляции. Это тонкий путь, который система усиливает тот факт, что если вы используете только то, что вам действительно нужно, дела идут быстрее.
Как правило, я всегда использую объявления @class в своих заголовочных файлах и только #import суперкласс. Это согласуется с предложениями Бена, но я думал, что стоит отметить, что даже если вас не беспокоят круговые ссылки, это хорошая идея ограничить #imports в файлах заголовков, если вы можете.