Objective-C类型检查和动态绑定详解 – Objective-C开发教程

上一章Objective-C开发教程请查看:Objective-C协议(Protocol)用法解析
众所周知,多态就是父类的指针指向子类的对象,那么这是如何做到的呢?这是OC的运行时runtime使程序在运行时才确定对象的类型,以及实际调用的方法,因此,这又叫做动态类型。
动态类型识别是通过isa指针实现的,运行时根据对象的isa指针寻找实际的类型,找到对应的属性或方法。
Objective-C的代码会被翻译成C的代码运行,其实也就是说类的所有信息(属性和方法)都会转成C相应的形式,在C层对OC的类结构进行控制可以得到所谓的动态特性,因而动态特性是因为编译器的存在,而动态类型是在运行时进行类型检查的。
OC中一个对象调用指定的方法不是由编译器决定,而是由运行时决定的,这又叫做动态绑定。相反类型在编译的时候进行检查的,又称为静态类型检查,显式使用指定类型的都会有静态类型检查,如int等。
动态绑定和id类型一般的动态绑定实现使用id类型进行声明,id类型是一个类似void*的指针,也就是泛型,它的好处就是可以容纳任何类型的指针。
使用id类型声明的对象,编译器不会对其进行类型检查,只有在运行时才检查,并决定实际调用。不过即使如此,建议尽量少用,因为这样的代码很不清晰。
下面是一个动态绑定的例子:

#import < Foundation/Foundation.h>@interface Square:NSObject { float area; }- (void)calculateAreaOfSide:(CGFloat)side; - (void)printArea; @end@implementation Square - (void)calculateAreaOfSide:(CGFloat)side { area = side * side; }- (void)printArea { NSLog(@"正方形面积: %f",area); }@end@interface Rectangle:NSObject { float area; }- (void)calculateAreaOfLength:(CGFloat)length andBreadth:(CGFloat)breadth; - (void)printArea; @end@implementationRectangle- (void)calculateAreaOfLength:(CGFloat)length andBreadth:(CGFloat)breadth { area = length * breadth; }- (void)printArea { NSLog(@"长方形 %f",area); }@endint main() { Square *square = [[Square alloc]init]; [square calculateAreaOfSide:10.0]; Rectangle *rectangle = [[Rectangle alloc]init]; [rectangle calculateAreaOfLength:10.0 andBreadth:5.0]; NSArray *shapes = [[NSArray alloc]initWithObjects: square, rectangle,nil]; id object1 = [shapes objectAtIndex:0]; // 动态绑定 [object1 printArea]; id object2 = [shapes objectAtIndex:1]; // 动态绑定 [object2 printArea]; return 0; }

类的前置声明我们可以通过使用编译指令@class告诉编译器某个符号是一个类名,这种写法称为类的前置声明。多个类使用逗号隔开,以分号结束,前置声明也可以声明多次,如下例子:
@class NSString,NSArry,NSMutableArry;@class Volume;

但是要注意,@class仅仅是告诉编译器符号是类名,这可以提高编译速度,但是使用到类的属性和方法,则需要导入头文件。
【Objective-C类型检查和动态绑定详解 – Objective-C开发教程】类的前置声明的主要使用是:累互相嵌套包含的时候,可以使用类的前置声明解决。

    推荐阅读