@class Foo与导入“Foo.h”有什么区别?

时间:2010-09-27 20:56:33

标签: objective-c import declaration

使用这些代码时有什么区别:

#import <UIKit/UIKit.h>
#import "Foo.h"

@interface EditFooViewController : UIViewController {
  Foo *foo;
}
@end

#import <UIKit/UIKit.h>

@class Foo;

@interface EditFooViewController : UIViewController {
  Foo *foo;
}
@end

4 个答案:

答案 0 :(得分:2)

我相信你寻求的答案是here

答案 1 :(得分:2)

前者导入头文件Foo.h,根据惯例,可能(但不一定)声明一个名为Foo的类。

后者声明你的代码中的其他地方,你将定义一个名为Foo的类,所以可以像Foo *foo;这样做,你可以信任我这个类{ {1}}存在。

你倾向于使用Foo,你有循环类依赖;即,类@class Foo声明类型为Foo的实例变量,而类Bar声明类型为Bar的实例变量。

答案 2 :(得分:1)

第二个变体forward声明了Foo,这意味着编译器将知道存在一个类Foo,但没有更多关于它的信息。即不是它的大小或成员。对于这里的用法,这是不需要的。

第二种变体有时可能优于第一种变体,因为它限制了依赖性。即,EditFooViewController的用户不需要依赖Foo.h。

答案 3 :(得分:1)

@class Foo;是“前瞻性声明”。考虑编译器实际看到的内容很有用:编译器总是一次编译一个.m文件。在EditFooViewController.m文件中,您可能从:

开始
#import "EditFooViewController.h"
#import "Foo.h"

那么在那时,编译器实际看到的是:

...the contents of UIKit.h

@class Foo;
@interface EditFooViewController : UIViewController {
    Foo *foo;
@end

...the contents of Foo.h, i.e.
@interface Foo
    ...
@end

...the contents of your .m file.

正如您所看到的,您可以声明引用Foo类的EditFooViewController的接口,但是当EditFooViewController.m导入Foo.h时,它实际上定义在它下面。

实际上,只要你的类引用了ivars或方法声明中的其他类,你就应该使用前向声明(即@class Foo;)。

例外情况是,如果您的类是子类或实现协议,您需要实际#import定义协议或超类的头文件。这是因为当第三个类导入子类的头文件时,它需要超类/原型的声明,并且您不希望必须导入所有超类/原型的头文件。这也解释了为什么你需要头文件顶部的#import <UIKit/UIKit.h>(而不是简单地将超类声明为@class UIViewController;)。