标题#import与@class [英] Headers #import versus @class

查看:108
本文介绍了标题#import与@class的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述


可能重复:

@class vs. #import

在.h文件中,您可以添加通过使用

In the .h file you can add a class to be seen(dont know what the correct terminolgy for this is) by using

#import "SomeClass.h"

或改为使用

@class SomeClass;

我尝试了两种方法,但它们都有效。有什么不同?我应该使用其中一种方法而不是其他方法吗?什么是最佳做法?

I've tried both methods and they both worked. Whats the difference? Should I be using one of the methods and not the other? What is best practice?

推荐答案

#import 包含的内容源头中的标题。
因此,导入标题中的每个声明也会被导入。

#import includes the content of the header in the source. Thus, every declaration which is in the imported header is also imported.

@class 仅声明到编译器,给定的类存在,但不导入标头本身。它被称为前向声明,因为您只向编译器声明该类存在之前详细定义它(告诉它实现了哪些方法等等)

@class only declares to the compiler that the given class exists, but does not import the header itself. It is called a forward declaration, as you only declares to the compiler that the class exists before defining it in details (telling which methods it implements and so on)

后果:


  • 使用 #import 在你的 .m 文件中,如果标题被修改,它将触发重新编译 .m 在下次编译时将文件 #import 下载。相反,如果你使用 @class ,你的 .m 不依赖于标题,如果标题被修改, .m 文件未重新编译。

  • 使用 @class 也避免交叉进口,例如如果A类引用B类而B类引用A类,则Bh <$ c中不能 #importAh $ c> #import Bh 同时在Ah中(这将是一个导入无限循环)

  • 使用 @class 只声明一个类存在,并且不告诉编译器该类响应的方法。

  • When using #import in your .m file, if the header is modified, it will trigger the recompilation of the .m file that #import it on next compilation. Instead, if you use @class, your .m does not depend on the header and if the header is modified, the .m file is not recompiled.
  • Using @class also avoid cross-imports, e.g. if the class A references class B and class B references class A, then you can't #import "A.h" in B.h and #import B.h in A.h in the same time (it would be an "import infinite loop")
  • Using @class only declare that a class exists and does not tell the compiler which methods the class responds to.

这个为什么通常最佳做法是在引用A类的标题(.h)文件中使用 @class A 转发声明该类,只是为了让编译器知道A是一个已知的类,但不需要知道更多, #import啊在实现中(。 m)文件,以便您可以在源文件中调用A类对象上的方法。

This is why usually the best practice is to forward-declare the class using @class A in the header (.h) files that references class A, just so that the compiler knows that "A" is a known class but doesn't need to know more, and #import "A.h" in the implementation (.m) file so that you can call methods on the objet of class A in your source file.

除了避免导入循环,这个如果不需要,也会避免重新编译文件,从而减少编译时间。

唯一的删除eptions是当你的类的声明继承另一个类,或者它声明它符合给定的 @protocol (如委托协议等)时,因为在这个特定的例如,编译器需要你 #import 父类的整个定义或 @protocol (要知道你的class正确符合这个给定的协议)。

The only exceptions are when the declaration of your class inherits another class, or when it declares that it conforms to a given @protocol (like delegate protocols and so on), because in this particular case, the compiler needs you to #import the whole definition of the parent class or @protocol (to know if your class correctly conforms to this given protocol).

MyClassA.h

MyClassA.h

// Tells the compiler that "MyClassB" is a class, that we will define later
@class MyClassB; // no need to #import the whole class, we don't need to know the whole definition at this stage

@interface MyClassA : NSObject {
    MyClassB* someB; // ok, the compiler knows that MyClassB is a class, that's all it needs to know so far
}
-(void)sayHello;
-(void)makeBTalk;
@end

MyClassB.h

MyClassB.h

@class MyClassA; // forward declaration here too
// anyway we couldn't #import "MyClassA.h" here AND #import "MyClassB.h" in MyClassA.h as it would create an unsolvable import loop for the compiler
@interface MyClassB : NSObject {
    MyClassA* someA; // ok, the compiler knows that MyClassA is a class, that's all it needs to know so far
}
-(void)talk;
-(void)makeABePolite;
@end

MyClassA.m

MyClassA.m

// import MyClassB so that we know the whole definition of MyClassB, including the methods it declares
#import "MyClassB.h" // thus we here know the "-talk" method of MyClassB and we are able to call it

@implementation MyClassA
-(void)sayHello { NSLog(@"A says Hello"); }
-(void)makeBTalk {
  [someB talk];
  // we can call the 'talk' method because we #imported the MyClassB header and knows this method exists
}
@end

MyClassB.m

MyClassB.m

// import MyClassA so that we know the methods it declares and can call them
#import "MyClassA.h"
@implementation MyClassB
-(void)talk { NSLog(@"B is talking"); }
-(void)makeABePolite {
  [someA sayHello];
  // we can call this because we #import MyClassA
}
@end

PS:请注意,如果这是最佳做法,我知道很多开发人员(包括我自己有时^^) #import 标题它需要在他们的.h文件中,而不是仅使用 @class 向前声明...这是一个坏习惯 - 或者因为这些开发人员不知道这些微妙之处 - 无论如何,您将不幸遇到现有代码。

PS: Note that if this is a best practice, I know a lot of developers (including myself sometimes ^^) that #import the header it needs in their .h files, instead of only forward-declare it using @class... this is some bad habit — or because these developers doesn't know these subtleties — that you will unfortunately encounter in existing code anyway.

这篇关于标题#import与@class的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆