#import和@class有什么区别,什么时候应该使用另一个?

时间:2022-01-19 20:47:53

I've been teaching myself Objective-C over the past month or so (I'm a Java head) and I've got my brain wrapped around most of it now. One thing that's confusing me at the moment: What's the difference between importing a class via @class vs doing a #import?

在过去一个月左右的时间里,我一直在教自己Objective-C(我是一名Java负责人),现在我的大脑已经被大部分包围了。有一件事让我感到困惑:通过@class导入一个类与进行#import之间的区别是什么?

Is one better than another one, or do I need to use one instead of the other in certain cases? I've been using just #import so far.

一个比另一个好,还是在某些情况下我需要使用一个而不是另一个?到目前为止我一直在使用#import。

3 个解决方案

#1


66  

#import brings the entire header file in question into the current file; any files that THAT file #imports are also included. @class, on the other hand (when used on a line by itself with some class names), just tells the compiler "Hey, you're going to see a new token soon; it's a class, so treat it that way).

#import将整个头文件带入当前文件;那些文件#imports的文件也包括在内。另一方面,@ class(当在一行上使用某些类名时),只告诉编译器“嘿,你很快就会看到一个新的令牌;它是一个类,所以这样对待它”。

This is very useful when you've got the potential for 'circular includes'; ie, Object1.h makes reference to Object2, and Object2.h makes reference to Object1. If you #importboth files into the other, the compiler can get confused as it tries to #import Object1.h, looks in it and sees Object2.h; it tries to #import Object2.h, and sees Object1.h, etc.

当你有“循环包含”的潜力时,这非常有用;即,Object1.h引用Object2,Object2.h引用Object1。如果#importboth文件到另一个文件中,编译器可能会感到困惑,因为它尝试#import Object1.h,查看它并查看Object2.h;它尝试#import Object2.h,并看到Object1.h等。

If, on the other hand, each of those files has @class Object1; or @class Object2;, then there's no circular reference. Just be sure to actually #import the required headers into your implementation (.m) files.

另一方面,如果每个文件都有@class Object1;或@class Object2;,那么就没有循环引用。只需确保将所需的头文件#import导入到您的实现(.m)文件中。

#2


27  

@class is called a forward declaration. You're basically telling the compiler that the class exists but not anything about the class. Thus, it doesn't know stuff like its superclass and what methods it declares.

@class被称为前向声明。你基本上告诉编译器该类存在但不是关于该类的任何内容。因此,它不知道它的超类和它声明的方法之类的东西。

As a general rule, use @class in the .h and #import in the .m, if at all possible. Like Louis said, it'll help speed up compile times. There are times when you need to #import a class in the header, though. Cases I can think of right now are:

作为一般规则,如果可能的话,在.m中使用@class,在.m中使用#import。就像路易斯说的那样,它将有助于加快编译时间。有时你需要在头文件中#import一个类。我现在能想到的案例是:

  • You are subclassing another class
  • 你是另一个类的子类
  • You are implementing a protocol
  • 您正在实施协议

In these cases, you must #import the header file where the class or protocol is declared because the compiler needs to know the full class hierarchy of its parent classes and implementing protocols.

在这些情况下,您必须#import声明类或协议的头文件,因为编译器需要知道其父类的完整类层次结构并实现协议。

FWIW, you can forward declare protocols, too, so long as your not implementing them:

FWIW,你也可以转发声明协议,只要你不实现它们:

@protocol SomeProtocol;

@interface ...

- (id<SomeProtocol>)someMethod;

@end

#3


5  

The other thing you want to keep in mind is that #imports slow down your compile times, since it means the the compiler needs to pull and work through a lot more header files. This is mostly masked by the use of precompiled headers, but I have occasionally been handed projects that corss imported every header instead of using @class where appropriate, and fixing them can improve compile time. It is subtle way the the system reinforces the fact that if you only use what you actually need things go faster.

您要记住的另一件事是#imports减慢了编译时间,因为这意味着编译器需要提取并处理更多的头文件。这主要是通过使用预编译的头文件来掩盖的,但我偶尔会将项目转换为corss导入的每个头文件,而不是在适当的地方使用@class,修复它们可以缩短编译时间。这是一个微妙的方式,系统强化了这样一个事实:如果你只使用你真正需要的东西,事情就会更快。

As a general rule, I always use @class declarations in in my header files, and only #import the superclass. That falls in line with Ben's suggestions, but I thought it was worth noting that even if you are not worried about circular refs it is good idea to limit #imports in header files if you can.

作为一般规则,我总是在我的头文件中使用@class声明,并且只#import超类。这符合Ben的建议,但我认为值得注意的是,即使您不担心循环引用,如果可以,最好限制头文件中的#imports。

#1


66  

#import brings the entire header file in question into the current file; any files that THAT file #imports are also included. @class, on the other hand (when used on a line by itself with some class names), just tells the compiler "Hey, you're going to see a new token soon; it's a class, so treat it that way).

#import将整个头文件带入当前文件;那些文件#imports的文件也包括在内。另一方面,@ class(当在一行上使用某些类名时),只告诉编译器“嘿,你很快就会看到一个新的令牌;它是一个类,所以这样对待它”。

This is very useful when you've got the potential for 'circular includes'; ie, Object1.h makes reference to Object2, and Object2.h makes reference to Object1. If you #importboth files into the other, the compiler can get confused as it tries to #import Object1.h, looks in it and sees Object2.h; it tries to #import Object2.h, and sees Object1.h, etc.

当你有“循环包含”的潜力时,这非常有用;即,Object1.h引用Object2,Object2.h引用Object1。如果#importboth文件到另一个文件中,编译器可能会感到困惑,因为它尝试#import Object1.h,查看它并查看Object2.h;它尝试#import Object2.h,并看到Object1.h等。

If, on the other hand, each of those files has @class Object1; or @class Object2;, then there's no circular reference. Just be sure to actually #import the required headers into your implementation (.m) files.

另一方面,如果每个文件都有@class Object1;或@class Object2;,那么就没有循环引用。只需确保将所需的头文件#import导入到您的实现(.m)文件中。

#2


27  

@class is called a forward declaration. You're basically telling the compiler that the class exists but not anything about the class. Thus, it doesn't know stuff like its superclass and what methods it declares.

@class被称为前向声明。你基本上告诉编译器该类存在但不是关于该类的任何内容。因此,它不知道它的超类和它声明的方法之类的东西。

As a general rule, use @class in the .h and #import in the .m, if at all possible. Like Louis said, it'll help speed up compile times. There are times when you need to #import a class in the header, though. Cases I can think of right now are:

作为一般规则,如果可能的话,在.m中使用@class,在.m中使用#import。就像路易斯说的那样,它将有助于加快编译时间。有时你需要在头文件中#import一个类。我现在能想到的案例是:

  • You are subclassing another class
  • 你是另一个类的子类
  • You are implementing a protocol
  • 您正在实施协议

In these cases, you must #import the header file where the class or protocol is declared because the compiler needs to know the full class hierarchy of its parent classes and implementing protocols.

在这些情况下,您必须#import声明类或协议的头文件,因为编译器需要知道其父类的完整类层次结构并实现协议。

FWIW, you can forward declare protocols, too, so long as your not implementing them:

FWIW,你也可以转发声明协议,只要你不实现它们:

@protocol SomeProtocol;

@interface ...

- (id<SomeProtocol>)someMethod;

@end

#3


5  

The other thing you want to keep in mind is that #imports slow down your compile times, since it means the the compiler needs to pull and work through a lot more header files. This is mostly masked by the use of precompiled headers, but I have occasionally been handed projects that corss imported every header instead of using @class where appropriate, and fixing them can improve compile time. It is subtle way the the system reinforces the fact that if you only use what you actually need things go faster.

您要记住的另一件事是#imports减慢了编译时间,因为这意味着编译器需要提取并处理更多的头文件。这主要是通过使用预编译的头文件来掩盖的,但我偶尔会将项目转换为corss导入的每个头文件,而不是在适当的地方使用@class,修复它们可以缩短编译时间。这是一个微妙的方式,系统强化了这样一个事实:如果你只使用你真正需要的东西,事情就会更快。

As a general rule, I always use @class declarations in in my header files, and only #import the superclass. That falls in line with Ben's suggestions, but I thought it was worth noting that even if you are not worried about circular refs it is good idea to limit #imports in header files if you can.

作为一般规则,我总是在我的头文件中使用@class声明,并且只#import超类。这符合Ben的建议,但我认为值得注意的是,即使您不担心循环引用,如果可以,最好限制头文件中的#imports。