Основное правило: используйте @class
в файле заголовка и #import
в файле реализации. (Однако вам необходимо #import
суперкласс вашего класса. И в некоторых других случаях вам также необходимо использовать `#import 'в заголовке.)
#import
не эквивалентно #include
. Если файл будет included
много раз, он будет загружаться каждый раз, но с множеством #imports
одного и того же файла он все равно будет загружен только один раз.
Следовательно, основная причина использования @class
- не избегать циклических зависимостей, а сделать компиляцию быстрее.
Вот пример, когда вы должны использовать @class
//MYControl.h
@class MYControl; // Must use class
@protocol MYControlDelegate
-(void)control:(MYControl *)control didChangeToState:(UIControlState)state;
@end
@interface MYControl : UIControl
{
id<MYControlDelegate> delegate_;
}
@property (nonatomic, assign) id<MYControlDelegate> delegate;
@end
//MYControl.m
@implementation MYControl
@synthesize delegate = delegate_;
. . .
В этом случае импортировать нечего, потому что протокол делегата объявлен над основным классом в файле заголовка. Но вам все равно нужно иметь возможность ссылаться на основной класс, который еще не объявлен. Итак, что делает @class
, так это просто сообщает компилятору, что существует некий класс, который называется MYControl
и будет определен в какой-то момент. (Однако не во время выполнения. Класс будет определен в ходе компиляции.)
РЕДАКТИРОВАТЬ: Из руководства Objective-C:
Поскольку подобные объявления просто используют имя класса как тип и не зависят от каких-либо деталей интерфейса класса (его методов и переменных экземпляра), директива @class дает компилятору достаточное предупреждение о том, чего ожидать. Однако там, где фактически используется интерфейс класса (создаются экземпляры, отправляются сообщения), интерфейс класса должен быть импортирован. Обычно интерфейсный файл использует @class для объявления классов, а соответствующий файл реализации импортирует их интерфейсы (так как ему нужно будет создать экземпляры этих классов или отправить им сообщения).
Директива @class минимизирует объем кода, видимого компилятором и компоновщиком, и, следовательно, является самым простым способом дать прямое объявление имени класса. Будучи простым, он позволяет избежать потенциальных проблем, которые могут возникнуть при импорте файлов, которые импортируют другие файлы. Например, если один класс объявляет статически типизированную переменную экземпляра другого класса, и два их интерфейсных файла импортируют друг друга, ни один из классов не может правильно скомпилироваться.
Обратите внимание, что замкнутость упоминается в последнем предложении как одна из общего класса проблем, решаемых с помощью @class
.
29.07.2010