代码之家  ›  专栏  ›  技术社区  ›  elcool codeVerine

@class foo和import“foo.h”有什么区别?

  •  1
  • elcool codeVerine  · 技术社区  · 14 年前

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

    #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 回复  |  直到 14 年前
        1
  •  1
  •   Daniel Dickison    14 年前

    @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时,它实际上是在它下面定义的。

    在实践中,每当您的类引用ivar或方法声明中的其他类时,您应该使用正向声明(即 @班福; )

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

        2
  •  2
  •   Community Mike Causer    7 年前

    我相信你的答案是 here .

        3
  •  2
  •   Simon Whitaker    14 年前

    前者导入一个头文件, Foo.h ,根据约定,它可能(但不一定)声明一个名为 Foo .

    后者声明在代码的其他地方,您将定义一个名为 所以可以做这样的事情 Foo *foo; 你可以相信我的课 存在。

    你倾向于使用 @class Foo 如果存在循环类依赖关系,即在何处类 声明类型为的实例变量 Bar 和班 酒吧 声明类型为的实例变量 .

        4
  •  1
  •   harald    14 年前

    第二个变量forward声明foo,这意味着编译器将知道存在一个类foo,但没有更多的内容。也就是说,不是它的大小或成员。对于这里的用法,这是不需要的。

    第二种变体有时比第一种变体更好,因为它限制了依赖性。即editfooviewcontroller的用户不需要依赖foo.h。