В чем разница между #import и @class и когда лучше использовать один?

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

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


person rustyshelf    schedule 31.10.2008    source источник


Ответы (3)


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

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

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

person Ben Gottlieb    schedule 31.10.2008
comment
Бен, Бен, вам не нужно отвечать на КАЖДЫЙ вопрос о Cocoa в Stack Overflow. Вы сгорите! - person schwa; 31.10.2008

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

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

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

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

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

@protocol SomeProtocol;

@interface ...

- (id<SomeProtocol>)someMethod;

@end
person Dave Dribin    schedule 31.10.2008

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

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

person Louis Gerbarg    schedule 31.10.2008