Основное правило: используйте @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
.