@class和#import有什么区别

时间:2021-08-21 13:36:17

When I compile with the following code there are no errors:

当我使用以下代码编译时,没有错误:

@class RootViewController;
//#import "RootViewController.h"

When I compile with the following code I get an error:

当我使用以下代码编译时,我收到一个错误:

//@class RootViewController;
#import "RootViewController.h"

"error: expected specifier-qualifier-list before 'RootViewController'"

“错误:'RootViewController'之前的预期说明符 - 限定符列表”

I don't understand what the difference is between the two because I used #import in a similar class and it compiled without errors!

我不明白两者之间的区别是什么,因为我在类似的类中使用了#import并且编译时没有错误!

8 个解决方案

#1


25  

@class is used when you need to know the name of a class in a particular file, but you don't need to know any details about the class (its methods, for example). #import is used when you actually need to use the class (i.e., send it a message).

当您需要知道特定文件中类的名称时使用@class,但您不需要知道有关该类的任何详细信息(例如,其方法)。当您确实需要使用该类时(即,向其发送消息),将使用#import。

For example, if you're declaring instance variables in a header file, you can use @class to declare an instance variable of a certain type:

例如,如果要在头文件中声明实例变量,则可以使用@class声明某种类型的实例变量:

@class MyOtherClass;

@interface MyClass : NSObject
{
    MyOtherClass *myIvar;
}
@end

Since you're not using myIvar yet, you don't need to know anything about it except that the type MyOtherClass exists.

由于您还没有使用myIvar,除了存在MyOtherClass类型之外,您不需要了解它。

However:

#import "MyOtherClass.h"

- (void)doSomething
{
    [myIvar doSomethingElse];
}

In this case, you're sending the doSomethingElse message to myIvar; the compiler needs to know that instances of MyOtherClass define this method, so you have to import the header file or the compiler will complain.

在这种情况下,您将doSomethingElse消息发送到myIvar;编译器需要知道MyOtherClass的实例定义了这个方法,所以你必须导入头文件或编译器会抱怨。

Why worry about this?

为什么要担心这个?

It mostly has to do with dependencies. When you #import file A into file B, file B becomes dependent upon file A -- that is, if file A changes, you'll have to recompile file B. If you use @class in file B, file B is not dependent on file A, and thus doesn't need to be recompiled when file A changes -- so if you're just declaring a type and not actually dependent upon the implementation of file A, you can save yourself compilation time by not #importing file A.

它主要与依赖关系有关。当#import文件A到文件B时,文件B变得依赖于文件A - 也就是说,如果文件A改变,你将不得不重新编译文件B.如果你在文件B中使用@class,文件B不依赖在文件A上,因此当文件A更改时不需要重新编译 - 所以如果你只是声明一个类型而不是实际上依赖于文件A的实现,你可以通过#importing文件来节省编译时间一个。

#2


8  

I decided to refer to the documentation because I was still confused:

我决定参考文档,因为我仍然感到困惑:

#import

This directive is identical to #include, except that it makes sure that the same file is never included more than once. It’s therefore preferred and is used in place of #include in code examples throughout Objective-C–based documentation.

该指令与#include相同,只是它确保同一个文件永远不会包含多次。因此,它是首选的,并且在代码示例中用于基于Objective-C的文档中的#include。

This convention means that every interface file includes, indirectly, the interface files for all inherited classes. When a source module imports a class interface, it gets interfaces for the entire inheritance hierarchy that the class is built upon.

此约定意味着每个接口文件间接包含所有继承类的接口文件。当源模块导入类接口时,它将获取构建该类的整个继承层次结构的接口。

@class

Declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the @class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported.

像这样的声明只是使用类名作为类型而不依赖于类接口的任何细节(它的方法和实例变量),@ class指令给编译器足够的预警预期。但是,在实际使用类的接口(创建实例,发送消息)的情况下,必须导入类接口。

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123

#3


6  

@class is used to avoid circular dependency... This prevents circular references where in one header A imports a second header B which(B) imports the first(A) which imports the second (B)and so on in an endless cycle....@class is generally used to ask compiler to look for its definition at runtime... especially when it resides in some static library..

@class用于避免循环依赖...这可以防止循环引用,其中在一个标题A中导入第二个标题B,其中(B)导入第一个(A),其导入第二个(B),以及在无限循环中依此类推。 ... @ class通常用于要求编译器在运行时查找其定义...尤其是当它驻留在某个静态库中时...

Other than that #import works

除此之外#import有效

See this question

看到这个问题

#4


6  

Basic rule: use @class in you header file and #import in your implementation file. (However, you need to #import your class' superclass. And in some other circumstances you also need to use `#import" in the header.)

基本规则:在头文件中使用@class,在实现文件中使用#import。 (但是,你需要#import你的类'超类。在其他一些情况下你还需要在标题中使用`#import。)

#import is not equivalent to #include. If a file is included many times, it will be loaded each time, but with many #imports of the same file, it will still only be loaded once.

#import不等同于#include。如果一个文件被多次包含,它将每次加载,但是对于同一文件的许多#imports,它仍将只加载一次。

Therefore, the main reason to use @class is not to avoid circular dependencies, but to make compilation faster.

因此,使用@class的主要原因不是为了避免循环依赖,而是为了使编译更快。

Here's an example of when you must use @class

这是一个必须使用@class的例子

//MYControl.h

@class MYControl;  // Must use class

@protocol MYControlDelegate
-(void)control:(MYControl *)control didChangeToState:(UIControlState)state;
@end

@interface MYControl : UIControl
{
   id<MYControlDelegate> delegate_;
}
@property (nonatomic, assign) id<MYControlDelegate> delegate;
@end

//MYControl.m

@implementation MYControl
@synthesize delegate = delegate_;
. . .

In this case, there is nothing to import, because the delegate protocol is declared above the main class in the header file. But you still need to be able to refer to the main class which has not yet been declared. So what @class does is to just let the compiler know that there is some class that is called MYControl and will be defined at some point. (Not at runtime however. The class will be defined in the course of the compilation.)

在这种情况下,没有要导入的内容,因为委托协议在头文件中的主类上面声明。但是你仍然需要能够引用尚未声明的主类。所以@class做的是让编译器知道有一些叫做MYControl的类,并且会在某个时候定义。 (但不是在运行时。该类将在编译过程中定义。)

EDIT: From the Objective-C manual:

编辑:从Objective-C手册:

Since declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the @class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported. Typically, an interface file uses @class to declare classes, and the corresponding implementation file imports their interfaces (since it will need to create instances of those classes or send them messages).

由于这样的声明只是使用类名作为类型而不依赖于类接口的任何细节(它的方法和实例变量),所以@class指令给编译器足够的预警预期。但是,在实际使用类的接口(创建实例,发送消息)的情况下,必须导入类接口。通常,接口文件使用@class来声明类,相应的实现文件会导入它们的接口(因为它需要创建这些类的实例或向它们发送消息)。

The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly.

@class指令最小化了编译器和链接器看到的代码量,因此是给出类名前向声明的最简单方法。简单,它避免了导入导入其他文件的文件时可能出现的潜在问题。例如,如果一个类声明另一个类的静态类型实例变量,并且它们的两个接口文件相互导入,则这两个类都不能正确编译。

Note that circularity is mentioned in the last sentence as one in a general class of issues dealt with by using @class.

请注意,在使用@class处理的一般问题类中,最后一句中提到了循环性。

#5


2  

@class:- It defines that you can create instance variable of the imported class and use it in your class.

@class: - 它定义您可以创建导入类的实例变量并在您的类中使用它。

import:- It defines that you can access the variables declared in the required imported class.

you can use given link for more info.

您可以使用给定的链接获取更多信息。

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123

#6


0  

@class means that the definition of the class RootViewController is not yet declared, but will be defined at run time. I believe it is like declaring an extern class in c++.

@class表示尚未声明类RootViewController的定义,但将在运行时定义。我相信它就像在c ++中声明一个extern类。

#import is equivalent to #include.

#import相当于#include。

by the error message i could guess you just made a mistake somewhere inside RootViewController.h, such as a forgotten ; or something like that

通过错误消息,我猜你在RootViewController.h里面的某个地方犯了一个错误,比如一个被遗忘的;或类似的东西

#7


0  

you must have imported the this class in the class to which you want to import here. That is why you are getting error , but it can be rectify by @class example .

您必须在此处要导入的类中导入此类。这就是为什么你会收到错误,但它可以通过@class示例来纠正。

#8


0  

@class is a forward declaration, a good practice is to put them in the .h instead of #import for avoiding circular #import problem.

@class是一个前向声明,一个好的做法是将它们放在.h而不是#import中以避免循环#import问题。

#1


25  

@class is used when you need to know the name of a class in a particular file, but you don't need to know any details about the class (its methods, for example). #import is used when you actually need to use the class (i.e., send it a message).

当您需要知道特定文件中类的名称时使用@class,但您不需要知道有关该类的任何详细信息(例如,其方法)。当您确实需要使用该类时(即,向其发送消息),将使用#import。

For example, if you're declaring instance variables in a header file, you can use @class to declare an instance variable of a certain type:

例如,如果要在头文件中声明实例变量,则可以使用@class声明某种类型的实例变量:

@class MyOtherClass;

@interface MyClass : NSObject
{
    MyOtherClass *myIvar;
}
@end

Since you're not using myIvar yet, you don't need to know anything about it except that the type MyOtherClass exists.

由于您还没有使用myIvar,除了存在MyOtherClass类型之外,您不需要了解它。

However:

#import "MyOtherClass.h"

- (void)doSomething
{
    [myIvar doSomethingElse];
}

In this case, you're sending the doSomethingElse message to myIvar; the compiler needs to know that instances of MyOtherClass define this method, so you have to import the header file or the compiler will complain.

在这种情况下,您将doSomethingElse消息发送到myIvar;编译器需要知道MyOtherClass的实例定义了这个方法,所以你必须导入头文件或编译器会抱怨。

Why worry about this?

为什么要担心这个?

It mostly has to do with dependencies. When you #import file A into file B, file B becomes dependent upon file A -- that is, if file A changes, you'll have to recompile file B. If you use @class in file B, file B is not dependent on file A, and thus doesn't need to be recompiled when file A changes -- so if you're just declaring a type and not actually dependent upon the implementation of file A, you can save yourself compilation time by not #importing file A.

它主要与依赖关系有关。当#import文件A到文件B时,文件B变得依赖于文件A - 也就是说,如果文件A改变,你将不得不重新编译文件B.如果你在文件B中使用@class,文件B不依赖在文件A上,因此当文件A更改时不需要重新编译 - 所以如果你只是声明一个类型而不是实际上依赖于文件A的实现,你可以通过#importing文件来节省编译时间一个。

#2


8  

I decided to refer to the documentation because I was still confused:

我决定参考文档,因为我仍然感到困惑:

#import

This directive is identical to #include, except that it makes sure that the same file is never included more than once. It’s therefore preferred and is used in place of #include in code examples throughout Objective-C–based documentation.

该指令与#include相同,只是它确保同一个文件永远不会包含多次。因此,它是首选的,并且在代码示例中用于基于Objective-C的文档中的#include。

This convention means that every interface file includes, indirectly, the interface files for all inherited classes. When a source module imports a class interface, it gets interfaces for the entire inheritance hierarchy that the class is built upon.

此约定意味着每个接口文件间接包含所有继承类的接口文件。当源模块导入类接口时,它将获取构建该类的整个继承层次结构的接口。

@class

Declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the @class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported.

像这样的声明只是使用类名作为类型而不依赖于类接口的任何细节(它的方法和实例变量),@ class指令给编译器足够的预警预期。但是,在实际使用类的接口(创建实例,发送消息)的情况下,必须导入类接口。

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123

#3


6  

@class is used to avoid circular dependency... This prevents circular references where in one header A imports a second header B which(B) imports the first(A) which imports the second (B)and so on in an endless cycle....@class is generally used to ask compiler to look for its definition at runtime... especially when it resides in some static library..

@class用于避免循环依赖...这可以防止循环引用,其中在一个标题A中导入第二个标题B,其中(B)导入第一个(A),其导入第二个(B),以及在无限循环中依此类推。 ... @ class通常用于要求编译器在运行时查找其定义...尤其是当它驻留在某个静态库中时...

Other than that #import works

除此之外#import有效

See this question

看到这个问题

#4


6  

Basic rule: use @class in you header file and #import in your implementation file. (However, you need to #import your class' superclass. And in some other circumstances you also need to use `#import" in the header.)

基本规则:在头文件中使用@class,在实现文件中使用#import。 (但是,你需要#import你的类'超类。在其他一些情况下你还需要在标题中使用`#import。)

#import is not equivalent to #include. If a file is included many times, it will be loaded each time, but with many #imports of the same file, it will still only be loaded once.

#import不等同于#include。如果一个文件被多次包含,它将每次加载,但是对于同一文件的许多#imports,它仍将只加载一次。

Therefore, the main reason to use @class is not to avoid circular dependencies, but to make compilation faster.

因此,使用@class的主要原因不是为了避免循环依赖,而是为了使编译更快。

Here's an example of when you must use @class

这是一个必须使用@class的例子

//MYControl.h

@class MYControl;  // Must use class

@protocol MYControlDelegate
-(void)control:(MYControl *)control didChangeToState:(UIControlState)state;
@end

@interface MYControl : UIControl
{
   id<MYControlDelegate> delegate_;
}
@property (nonatomic, assign) id<MYControlDelegate> delegate;
@end

//MYControl.m

@implementation MYControl
@synthesize delegate = delegate_;
. . .

In this case, there is nothing to import, because the delegate protocol is declared above the main class in the header file. But you still need to be able to refer to the main class which has not yet been declared. So what @class does is to just let the compiler know that there is some class that is called MYControl and will be defined at some point. (Not at runtime however. The class will be defined in the course of the compilation.)

在这种情况下,没有要导入的内容,因为委托协议在头文件中的主类上面声明。但是你仍然需要能够引用尚未声明的主类。所以@class做的是让编译器知道有一些叫做MYControl的类,并且会在某个时候定义。 (但不是在运行时。该类将在编译过程中定义。)

EDIT: From the Objective-C manual:

编辑:从Objective-C手册:

Since declarations like this simply use the class name as a type and don’t depend on any details of the class interface (its methods and instance variables), the @class directive gives the compiler sufficient forewarning of what to expect. However, where the interface to a class is actually used (instances created, messages sent), the class interface must be imported. Typically, an interface file uses @class to declare classes, and the corresponding implementation file imports their interfaces (since it will need to create instances of those classes or send them messages).

由于这样的声明只是使用类名作为类型而不依赖于类接口的任何细节(它的方法和实例变量),所以@class指令给编译器足够的预警预期。但是,在实际使用类的接口(创建实例,发送消息)的情况下,必须导入类接口。通常,接口文件使用@class来声明类,相应的实现文件会导入它们的接口(因为它需要创建这些类的实例或向它们发送消息)。

The @class directive minimizes the amount of code seen by the compiler and linker, and is therefore the simplest way to give a forward declaration of a class name. Being simple, it avoids potential problems that may come with importing files that import still other files. For example, if one class declares a statically typed instance variable of another class, and their two interface files import each other, neither class may compile correctly.

@class指令最小化了编译器和链接器看到的代码量,因此是给出类名前向声明的最简单方法。简单,它避免了导入导入其他文件的文件时可能出现的潜在问题。例如,如果一个类声明另一个类的静态类型实例变量,并且它们的两个接口文件相互导入,则这两个类都不能正确编译。

Note that circularity is mentioned in the last sentence as one in a general class of issues dealt with by using @class.

请注意,在使用@class处理的一般问题类中,最后一句中提到了循环性。

#5


2  

@class:- It defines that you can create instance variable of the imported class and use it in your class.

@class: - 它定义您可以创建导入类的实例变量并在您的类中使用它。

import:- It defines that you can access the variables declared in the required imported class.

you can use given link for more info.

您可以使用给定的链接获取更多信息。

http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple_ref/doc/uid/TP30001163-CH12-TPXREF123

#6


0  

@class means that the definition of the class RootViewController is not yet declared, but will be defined at run time. I believe it is like declaring an extern class in c++.

@class表示尚未声明类RootViewController的定义,但将在运行时定义。我相信它就像在c ++中声明一个extern类。

#import is equivalent to #include.

#import相当于#include。

by the error message i could guess you just made a mistake somewhere inside RootViewController.h, such as a forgotten ; or something like that

通过错误消息,我猜你在RootViewController.h里面的某个地方犯了一个错误,比如一个被遗忘的;或类似的东西

#7


0  

you must have imported the this class in the class to which you want to import here. That is why you are getting error , but it can be rectify by @class example .

您必须在此处要导入的类中导入此类。这就是为什么你会收到错误,但它可以通过@class示例来纠正。

#8


0  

@class is a forward declaration, a good practice is to put them in the .h instead of #import for avoiding circular #import problem.

@class是一个前向声明,一个好的做法是将它们放在.h而不是#import中以避免循环#import问题。