在Objective-C中,能够使用#import和@class来引用别的类型, 可是你知道两者有什么差别吗?
在Objective-c中,当一个类须要引用还有一个类的接口时,须要在类的头文件里建立被引用类的指针
Person.h
@interface Person: NSObject
{
Woman *woman;
Man *man;
}
.......
假设直接编译,会出错,由于不知道Woman,Man是什么。
这时有两个选择,一是import这两个被引用类的头文件,还有一个是使用@class申明Woman和Man是类名,二者的差别:
1. import会包括这个类的全部信息。包括实体变量和方法。而@class仅仅是告诉编译器。其后面声明的名称是类的名称。至于这些类是怎样定义的。临时不用考虑,后面会再告诉你;
2. 在头文件里,一般仅仅须要知道被引用的类的名称就能够了,不须要知道其内部的实体变量和方法。所以在头文件里一般使用@class来声明这个名称是类的名称,而在类的实现部分。由于会用到这个引用类的内部的实体变量和方法,所以须要使用#import来包括这个被引用类的头文件。
3. 在编译效率方面考虑,假设你有100个头文件都#import了同一个头文件。或者这些文件是依次被引用的。如A–>B, B–>C, C–>D这种引用关系。当最開始的那个头文件有变化的话,后
面全部引用它的类都须要又一次编译,假设你的类有非常多的话,这将耗费大量的时间。而是用@class则不会。
4. 假设有循环依赖关系,如:A–>B, B–>A这种相互依赖关系,假设使用#import来相互包括。那么就会出现编译错误。假设使用@class在两个类的头文件里相互声明。则不会有编译错误出现。
@class叫做forward-class, 你常常会在头文件的定义中看到通过@class的引用, 原因就是当你仅仅用@class来引入一个类时, 编译器知道有这么一个类,也就是说它能识别Engine *engine;
而在implementation文件里,假设你想要訪问engine.price, 编译器就会出错, 即使你用了@class引入了. 这时须要使用的事实上是#import 来引入Engine.h这个头文件,它包含这个类的全部的定义, 它
知道你有定义一个price, 而通过@class引入的除了类本身之外,没有详细的信息.
#import<> 跟 #import""又什么差别?“”的意思是自己创建的文件,用这个首先会在当前的文件夹中寻找,假设找不到就到其它的位置寻找,“”和<>是相对的一个是自己创建的文件一个是系统的文件
更具体的分析:在Objective-c中,当一个类须要引用还有一个类的接口时,须要在类的头文件里建立被引用类的指针
Person.h
@interface Person: NSObject
{
Woman *woman;
Man *man;
}
.......
假设直接编译,会出错,由于不知道Woman,Man是什么。
这时有两个选择,一是import这两个被引用类的头文件,还有一个是使用@class申明Woman和Man是类名,二者的差别:
1. import会包括这个类的全部信息。包括实体变量和方法。而@class仅仅是告诉编译器。其后面声明的名称是类的名称。至于这些类是怎样定义的。临时不用考虑,后面会再告诉你;
2. 在头文件里,一般仅仅须要知道被引用的类的名称就能够了,不须要知道其内部的实体变量和方法。所以在头文件里一般使用@class来声明这个名称是类的名称,而在类的实现部分。由于会用到这个引用类的内部的实体变量和方法,所以须要使用#import来包括这个被引用类的头文件。
3. 在编译效率方面考虑,假设你有100个头文件都#import了同一个头文件。或者这些文件是依次被引用的。如A–>B, B–>C, C–>D这种引用关系。当最開始的那个头文件有变化的话,后
面全部引用它的类都须要又一次编译,假设你的类有非常多的话,这将耗费大量的时间。而是用@class则不会。
4. 假设有循环依赖关系,如:A–>B, B–>A这种相互依赖关系,假设使用#import来相互包括。那么就会出现编译错误。假设使用@class在两个类的头文件里相互声明。则不会有编译错误出现。
所以,一般来说。@class是放在interface中的,仅仅是为了在interface中引用这个类,把这个类作为一个类型来用的。 在实现这个接口的实现类中,假设须要引用这个类的实体变量或者方法之类的(存在继承关系或者代理)。还是须要import在@class中声明的类进来.