【发布时间】:2008-10-31 10:21:04
【问题描述】:
在过去一个月左右的时间里,我一直在自学 Objective-C(我是一名 Java 负责人),现在我的大部分内容都已经掌握了。目前让我感到困惑的一件事是:通过@class 导入类与执行#import 有什么区别?
是一种比另一种更好,还是在某些情况下我需要使用一种而不是另一种?到目前为止,我一直只使用#import。
【问题讨论】:
在过去一个月左右的时间里,我一直在自学 Objective-C(我是一名 Java 负责人),现在我的大部分内容都已经掌握了。目前让我感到困惑的一件事是:通过@class 导入类与执行#import 有什么区别?
是一种比另一种更好,还是在某些情况下我需要使用一种而不是另一种?到目前为止,我一直只使用#import。
【问题讨论】:
#import 将有问题的整个头文件带入当前文件;还包括该文件#imports 的任何文件。另一方面,@class(当在一行上单独使用某些类名时)只是告诉编译器“嘿,你很快就会看到一个新的标记;它是一个类,所以这样对待它)。
当您有“循环包含”的潜力时,这非常有用;即,Object1.h 引用Object2,Object2.h 引用Object1。如果您将#importboth 文件放入另一个文件中,编译器会在尝试#import Object1.h 时感到困惑,查看它并看到Object2.h;它尝试#importObject2.h,并看到Object1.h等。
另一方面,如果这些文件中的每一个都有@class Object1; 或@class Object2;,那么就没有循环引用。请务必将所需的标头实际#import 放入您的实现 (.m) 文件中。
【讨论】:
@class 称为前向声明。您基本上是在告诉编译器该类存在,但与该类无关。因此,它不知道它的超类以及它声明的方法之类的东西。
作为一般规则,如果可能,请在 .h 中使用 @class,在 .m 中使用 #import。就像 Louis 说的,这将有助于加快编译时间。不过,有时您需要在标题中 #import 一个类。我现在能想到的案例有:
在这些情况下,您必须 #import 声明类或协议的头文件,因为编译器需要知道其父类和实现协议的完整类层次结构。
FWIW,你也可以转发声明协议,只要你不实现它们:
@protocol SomeProtocol;
@interface ...
- (id<SomeProtocol>)someMethod;
@end
【讨论】:
您要记住的另一件事是#imports 会减慢您的编译时间,因为这意味着编译器需要提取并处理更多的头文件。这主要被预编译头文件的使用所掩盖,但我偶尔会收到一些项目,这些项目会交叉导入每个头文件,而不是在适当的地方使用@class,修复它们可以提高编译时间。系统以一种微妙的方式强化了这样一个事实,即如果你只使用你真正需要的东西,事情就会变得更快。
作为一般规则,我总是在我的头文件中使用@class 声明,并且只使用#import 超类。这符合 Ben 的建议,但我认为值得注意的是,即使您不担心循环引用,如果可以的话,最好在头文件中限制 #imports。
【讨论】: