Objective c @class Foo和import“Foo.h”之间有什么区别?

Objective c @class Foo和import“Foo.h”之间有什么区别?,objective-c,import,declaration,Objective C,Import,Declaration,使用这些代码时有什么区别: #import <UIKit/UIKit.h> #import "Foo.h" @interface EditFooViewController : UIViewController { Foo *foo; } @end 及 我相信您寻求的答案是。我相信您寻求的答案是。前者导入一个头文件Foo.h,根据惯例,它可能但不一定声明一个名为Foo的类 后者声明在代码的其他地方,您将定义一个名为Foo的类,因此可以执行Foo*Foo;,你可以相信Foo类的

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

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

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


我相信您寻求的答案是。

我相信您寻求的答案是。

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

后者声明在代码的其他地方,您将定义一个名为Foo的类,因此可以执行Foo*Foo;,你可以相信Foo类的存在


您倾向于使用@class Foo,其中您具有循环类依赖关系;i、 e.其中,类Foo声明了一个Bar类型的实例变量,类Bar声明了一个Foo类型的实例变量。

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

后者声明在代码的其他地方,您将定义一个名为Foo的类,因此可以执行Foo*Foo;,你可以相信Foo类的存在


您倾向于使用@class Foo,其中您具有循环类依赖关系;i、 例如,类Foo声明了一个Bar类型的实例变量,类Bar声明了一个Foo类型的实例变量。

第二个变量forward声明了Foo,这意味着编译器将知道存在一个Foo类,但仅此而已。即不是它的大小或成员。对于这里的用法,这是不需要的


第二种变体有时可能比第一种更可取,因为它限制了依赖性。也就是说,EditFooViewController的用户不需要依赖于Foo.h.

第二个变量forward声明Foo,这意味着编译器将知道存在一个类Foo,但仅此而已。即不是它的大小或成员。对于这里的用法,这是不需要的

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

@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.
如您所见,您可以为EditFooViewController声明引用Foo类的接口,但当EditFooViewController.m导入Foo.h时,它实际上是在它下面定义的

实际上,每当您的类引用IVAR或方法声明中的其他类时,都应该使用前向声明,即@class Foo

例外情况是,如果您的类是某个协议的子类或实现,则需要实际导入定义该协议或超类的头文件。这是因为当第三个类导入子类的头文件时,它需要超类/原型的声明,并且您不希望必须导入所有超类/原型的头文件。这也解释了为什么需要将导入放在头文件的顶部,而不是简单地将超类向前声明为@class UIViewController

@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.
如您所见,您可以为EditFooViewController声明引用Foo类的接口,但当EditFooViewController.m导入Foo.h时,它实际上是在它下面定义的

实际上,每当您的类引用IVAR或方法声明中的其他类时,都应该使用前向声明,即@class Foo

例外情况是,如果您的类是某个协议的子类或实现,则需要实际导入定义该协议或超类的头文件。这是因为当第三个类导入子类的头文件时,它需要超类/原型的声明,并且您不希望必须导入所有超类/原型的头文件。这也解释了为什么需要将导入放在头文件的顶部,而不是简单地将超类向前声明为@class UIViewController