前言:
oc中的指针类型变量有两个:一个是编译时类型,一个是运行时类型,编译时类型由声明该变量是使用的类型决定,运行时类型由实际赋给该变量的对象决定。如果编译时类型和运行时类型不一致,就有可能出现多态。
正文:
新建一个CHPerson类
1 @interface CHPerson : NSObject 2 -(void)eat; 3 -(void)play; 4 @end 5 --------------------------------------------------------- 6 #import "CHPerson.h" 7 8 @implementation CHPerson 9 -(void)eat{ 10 NSLog(@"----父类的吃"); 11 } 12 -(void)play{ 13 NSLog(@"-----父类的玩"); 14 } 15 @end
新建一个继承于CHPerson的CHchina类
1 #import "CHPerson.h" 2 3 @interface CHChina : CHPerson 4 -(void)playgame; 5 @end 6 7 ---------------------------------------------------- 8 9 #import "CHChina.h" 10 11 @implementation CHChina 12 -(void)eat{ 13 NSLog(@"=======子类的吃"); 14 } 15 -(void)playgame{ 16 NSLog(@"玩游戏"); 17 } 18 @end
调用方法:
1 #import "ViewController.h" 2 #import "CHChina.h" 3 @interface ViewController () 4 5 @end 6 7 @implementation ViewController 8 9 - (void)viewDidLoad { 10 [super viewDidLoad]; 11 // 下面编译时类型和运行时类型完全一样,因此不存在多态 12 CHPerson *person = [[CHPerson alloc]init]; 13 [person eat]; 14 15 // 下面编译时类型和运行时类型完全一样,因此不存在多态 16 CHChina *china = [[CHChina alloc]init]; 17 [china eat]; 18 19 // 下面编译时类型和运行时类型不一样,因此发生多态 20 CHPerson *perch = [[CHChina alloc]init]; 21 // 调用从父类继承的play方法 22 [perch play]; 23 // 调用子类重写eat方法 24 [perch eat]; 25 26 // 因为perch的编译时类型是CHPerson,但CHPerson没有playgame方法,所以编译时会报错 27 // [perch playgame]; 28 // 但可以将任何类型的指针变量赋值给id类型的变量 29 id allperch = perch;//下面会解释为何这样做? 30 [allperch playgame]; 31 32 }
结果:
1 2015-10-01 17:54:03.705 多态[86274:361586] ----父类的吃 13行代码结果 2 2015-10-01 17:54:03.705 多态[86274:361586] =======子类的吃 3 2015-10-01 17:54:03.706 多态[86274:361586] -----父类的玩 4 2015-10-01 17:54:03.706 多态[86274:361586] =======子类的吃 24行代码结果 5 2015-10-01 17:54:03.706 多态[86274:361586] 玩游戏
补充(id) :oc中提供了一个id类型,这个id类型可以代表所有对象的类型。就是说,任意类型的对象都可以赋值给id类型变量。
当通过id类型变量来调用方法时,oc将会执行动态绑定,动态绑定,是指oc将会跟踪对象所属类,它会在运行时判断该对象所属类,并在运行时确定需要动态调用的方法,而不是在编译时确定要调用的方法。如上面,程序会在运行时动态检测该变量所指的对象的实际类型为CHChina,所以会动态绑定到执行CHChina的eat方法。